Получить счет и детали документа - PullRequest
1 голос
/ 19 мая 2019

У меня есть такая коллекция:

[{
    "_id": "5ba6b67ab22f62939eba24cc",
    "voucher": "77-SRNP-4",
    "Collection Date": "1977-06-06T06:00:00.000Z",
    "Herbivore species": "Agrius cingulata",
    "Herbivore subfamily": "Sphinginae",
    "Latitude": "10.83764",
    "Longitude": "-85.61871"
}, {
    "_id": "5ba6b67ab22f62939eba24ea",
    "voucher": "78-SRNP-10",
    "Collection Date": "1978-05-20T06:00:00.000Z",
    "Herbivore species": "Xylophanes turbata",
    "Herbivore subfamily": "Macroglossinae",
    "Latitude": "10.80212",
    "Longitude": "-85.65372"
}, {
    "_id": "5ba6b67ab22f62939eba24eb",
    "voucher": "78-SRNP-10.02",
    "Collection Date": "1978-05-20T06:00:00.000Z",
    "Herbivore species": "Xylophanes turbata",
    "Herbivore subfamily": "Macroglossinae",
    "Latitude": "10.80212",
    "Longitude": "-85.65372"
}]

Я хотел бы получить количество видов, а также некоторые детали каждой записи по одному запросу. Что-то вроде опозита $unwind. Чтобы получить что-то вроде:

[{
    "Agrius cingulata": {
        count: 1,
        "Herbivore subfamily": "Sphinginae"
        records: [{
            "voucher": "77-SRNP-4",
            "Collection Date": "1977-06-06T06:00:00.000Z",
            "Latitude": "10.83764",
            "Longitude": "-85.61871"
        }]

    },
    "Xylophanes turbata": {
        count: 2,
        "Herbivore subfamily": "Macroglossinae",
        records: [
            {
                "voucher": "78-SRNP-10",
                "Collection Date": "1978-05-20T06:00:00.000Z",
                "Latitude": "10.80212",
                "Longitude": "-85.65372"
            },
            {
                "voucher": "78-SRNP-10.02",
                "Collection Date": "1978-05-20T06:00:00.000Z",
                "Latitude": "10.80212",
                "Longitude": "-85.65372"
            }
        ]
    }
}]

В настоящее время я работаю над двумя отдельными запросами: один для поиска записей, а другой для подсчета. Однако полезная нагрузка немного велика, и я полагаю, что мог бы уменьшить ее, если бы отправил только один раз информацию, которая повторяется, как подсемейство видов, а также свел вместе подсчеты и другие характеристики, но я не нашел подходящей агрегации.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 19 мая 2019

Основная концепция для "реверса $unwind" , конечно, равна $push. Поэтому в основном это то, что вы делаете, с некоторым дополнительным использованием $first, где это уместно, а также $arrayToObject и $objectToArray вместе с $filter, поскольку не нужно указывать каждое поле в документе, особенно когда в документе на самом деле имеется намного больше полей, чем представлено в вопросе.

Следующее является довольно общим и не имеет значения, сколько других полей присутствуют в документе:

db.collection.aggregate([
  { "$group": {
    "_id": "$Herbivore species",
    "count": { "$sum": 1 },
    "Herbivore subfamily": { "$first": "$Herbivore subfamily" },
    "records": {
      "$push": {
        "$arrayToObject": {
          "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "cond": { "$not": { "$in": [ "$$this.k", ["Herbivore subfamily", "Herbivore species"] ] } }
          }
        }
      }
    }
  }}
])

Это приведет к такому результату:

{
        "_id" : "Agrius cingulata",
        "count" : 1,
        "Herbivore subfamily" : "Sphinginae",
        "records" : [
                {
                        "_id" : "5ba6b67ab22f62939eba24cc",
                        "voucher" : "77-SRNP-4",
                        "Collection Date" : "1977-06-06T06:00:00.000Z",
                        "Latitude" : "10.83764",
                        "Longitude" : "-85.61871"
                }
        ]
}
{
        "_id" : "Xylophanes turbata",
        "count" : 2,
        "Herbivore subfamily" : "Macroglossinae",
        "records" : [
                {
                        "_id" : "5ba6b67ab22f62939eba24ea",
                        "voucher" : "78-SRNP-10",
                        "Collection Date" : "1978-05-20T06:00:00.000Z",
                        "Latitude" : "10.80212",
                        "Longitude" : "-85.65372"
                },
                {
                        "_id" : "5ba6b67ab22f62939eba24eb",
                        "voucher" : "78-SRNP-10.02",
                        "Collection Date" : "1978-05-20T06:00:00.000Z",
                        "Latitude" : "10.80212",
                        "Longitude" : "-85.65372"
                }
        ]
}

Не точно , что было задано в вопросе, поскольку, конечно, точно не показывает "ключи" результата в том виде, в котором он был запрошен. Но это может быть исправлено с помощью второй стадии $group вместе с теми же операторами, которые были показаны ранее:

db.collection.aggregate([
  { "$group": {
    "_id": "$Herbivore species",
    "count": { "$sum": 1 },
    "Herbivore subfamily": { "$first": "$Herbivore subfamily" },
    "records": {
      "$push": {
        "$arrayToObject": {
          "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "cond": { "$not": { "$in": [ "$$this.k", ["Herbivore subfamily", "Herbivore species"] ] } }
          }
        }
      }
    }
  }},
  { "$group": {
    "_id": null,
    "content": {
      "$mergeObjects": {
        "$arrayToObject": [[
          { "k": "$_id",
            "v": {
              "$arrayToObject": {
                "$filter": {
                  "input": { "$objectToArray": "$$ROOT" },
                  "cond": { "$ne": ["$$this.k", "_id"] }
                }
              }
            }
          }
        ]]
      }
    }
  }},
  { "$replaceRoot": { "newRoot": "$content" } }
])

Что возвращает:

{
        "Xylophanes turbata" : {
                "count" : 2,
                "Herbivore subfamily" : "Macroglossinae",
                "records" : [
                        {
                                "_id" : "5ba6b67ab22f62939eba24ea",
                                "voucher" : "78-SRNP-10",
                                "Collection Date" : "1978-05-20T06:00:00.000Z",
                                "Latitude" : "10.80212",
                                "Longitude" : "-85.65372"
                        },
                        {
                                "_id" : "5ba6b67ab22f62939eba24eb",
                                "voucher" : "78-SRNP-10.02",
                                "Collection Date" : "1978-05-20T06:00:00.000Z",
                                "Latitude" : "10.80212",
                                "Longitude" : "-85.65372"
                        }
                ]
        },
        "Agrius cingulata" : {
                "count" : 1,
                "Herbivore subfamily" : "Sphinginae",
                "records" : [
                        {
                                "_id" : "5ba6b67ab22f62939eba24cc",
                                "voucher" : "77-SRNP-4",
                                "Collection Date" : "1977-06-06T06:00:00.000Z",
                                "Latitude" : "10.83764",
                                "Longitude" : "-85.61871"
                        }
                ]
        }
}

Или, если вы предпочитаете (так как это не меняет объем возвращаемых данных в любом случае), вы можете просто «преобразовать» в форму «ключ / значение» возвращаемого документа в клиентском коде после того, как результат будет возвращен из MongoDB. Простой пример JavaScript-оболочки:

db.collection.aggregate([
  { "$group": {
    "_id": "$Herbivore species",
    "count": { "$sum": 1 },
    "Herbivore subfamily": { "$first": "$Herbivore subfamily" },
    "records": {
      "$push": {
        "$arrayToObject": {
          "$filter": {
            "input": { "$objectToArray": "$$ROOT" },
            "cond": { "$not": { "$in": [ "$$this.k", ["Herbivore subfamily", "Herbivore species"] ] } }
          }
        }
      }
    }
  }},
  /*
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": [[
        { "k": "$_id",
          "v": {
            "$arrayToObject": {
              "$filter": {
                "input": { "$objectToArray": "$$ROOT" },
                "cond": { "$ne": ["$$this.k", "_id"] }
              }
            }
          }
        }
      ]]
    }
  }}
  */
]).toArray().reduce((o,{ _id, ...rest }) => ({ ...o, [_id]: rest }),{})

И тот же результат:

{
        "Xylophanes turbata" : {
                "count" : 2,
                "Herbivore subfamily" : "Macroglossinae",
                "records" : [
                        {
                                "_id" : "5ba6b67ab22f62939eba24ea",
                                "voucher" : "78-SRNP-10",
                                "Collection Date" : "1978-05-20T06:00:00.000Z",
                                "Latitude" : "10.80212",
                                "Longitude" : "-85.65372"
                        },
                        {
                                "_id" : "5ba6b67ab22f62939eba24eb",
                                "voucher" : "78-SRNP-10.02",
                                "Collection Date" : "1978-05-20T06:00:00.000Z",
                                "Latitude" : "10.80212",
                                "Longitude" : "-85.65372"
                        }
                ]
        },
        "Agrius cingulata" : {
                "count" : 1,
                "Herbivore subfamily" : "Sphinginae",
                "records" : [
                        {
                                "_id" : "5ba6b67ab22f62939eba24cc",
                                "voucher" : "77-SRNP-4",
                                "Collection Date" : "1977-06-06T06:00:00.000Z",
                                "Latitude" : "10.83764",
                                "Longitude" : "-85.61871"
                        }
                ]
        }
}

Вероятно, главное, что нужно понять, это "агрегирование" (то, что делает первый представленный этап), вероятно, это то, что вы действительно хотите, чтобы сервер баз данных делал. Вы можете использовать «причудливые» операторы или , а не , в зависимости от имеющейся версии MongoDB. Однако «преобразования конечного результата» , как было продемонстрировано как вторая фаза в примерах, приведенных здесь, вероятно, является чем-то, что вы действительно хотите сделать вместо этого, принимая клиентский и обрабатывающий код. Обычно это намного проще и понятнее.

0 голосов
/ 19 мая 2019

Попробуйте это:

db.collection.aggregate([
    {
        $group: {
            _id: "$Herbivore species",
            records: { $push: { Longitude: "$Longitude", Latitude: "$Latitude", "Collection Date": "$Collection Date", voucher: "$voucher" } },
            count : { $sum :1}
        }
    }
])

Результаты:

{
    "_id" : "Xylophanes turbata",
    "records" : [
        {
            "Longitude" : "-85.65372",
            "Latitude" : "10.80212",
            "Collection Date" : "1978-05-20T06:00:00.000Z",
            "voucher" : "78-SRNP-10"
        },
        {
            "Longitude" : "-85.65372",
            "Latitude" : "10.80212",
            "Collection Date" : "1978-05-20T06:00:00.000Z",
            "voucher" : "78-SRNP-10.02"
        }
    ],
    "count" : 2
},

/* 2 */
{
    "_id" : "Agrius cingulata",
    "records" : [
        {
            "Longitude" : "-85.61871",
            "Latitude" : "10.83764",
            "Collection Date" : "1977-06-06T06:00:00.000Z",
            "voucher" : "77-SRNP-4"
        }
    ],
    "count" : 1
}

Для групп "Травоядные виды" и "Подсемейство травоядных" вы можете попробовать, как показано ниже:

db.collection.aggregate([
    {
        $group: {
            _id: { "Herbivore species" :"$Herbivore species" , "Herbivore subfamily": "$Herbivore subfamily" },
            records: { $push: { Longitude: "$Longitude", Latitude: "$Latitude", "Collection Date": "$Collection Date", voucher: "$voucher" } },
            count : { $sum :1}
        }
    }
])

Результат будет таким, как показано ниже:

{
    "_id" : {
        "Herbivore species" : "Xylophanes turbata",
        "Herbivore subfamily" : "Macroglossinae"
    },
    "records" : [
        {
            "Longitude" : "-85.65372",
            "Latitude" : "10.80212",
            "Collection Date" : "1978-05-20T06:00:00.000Z",
            "voucher" : "78-SRNP-10"
        },
        {
            "Longitude" : "-85.65372",
            "Latitude" : "10.80212",
            "Collection Date" : "1978-05-20T06:00:00.000Z",
            "voucher" : "78-SRNP-10.02"
        }
    ],
    "count" : 2
},

/* 2 */
{
    "_id" : {
        "Herbivore species" : "Agrius cingulata",
        "Herbivore subfamily" : "Sphinginae"
    },
    "records" : [
        {
            "Longitude" : "-85.61871",
            "Latitude" : "10.83764",
            "Collection Date" : "1977-06-06T06:00:00.000Z",
            "voucher" : "77-SRNP-4"
        }
    ],
    "count" : 1
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...