Посчитайте _id вхождения в другой коллекции - PullRequest
0 голосов
/ 25 сентября 2018

У нас есть структура БД, подобная следующей:

Владельцы домашних животных:

/* 1 */
{
    "_id" : ObjectId("5baa8b8ce70dcbe59d7f1a32"),
    "name" : "bob"
}

/* 2 */
{
    "_id" : ObjectId("5baa8b8ee70dcbe59d7f1a33"),
    "name" : "mary"
}

Домашние животные:

/* 1 */
{
    "_id" : ObjectId("5baa8b4fe70dcbe59d7f1a2a"),
    "name" : "max",
    "owner" : ObjectId("5baa8b8ce70dcbe59d7f1a32")
}

/* 2 */
{
    "_id" : ObjectId("5baa8b52e70dcbe59d7f1a2b"),
    "name" : "charlie",
    "owner" : ObjectId("5baa8b8ce70dcbe59d7f1a32")
}

/* 3 */
{
    "_id" : ObjectId("5baa8b53e70dcbe59d7f1a2c"),
    "name" : "buddy",
    "owner" : ObjectId("5baa8b8ee70dcbe59d7f1a33")
}

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

db.getCollection('owners').aggregate([
    { $lookup: { from: 'pets', localField: '_id', foreignField: 'owner', as: 'pets' } },
    { $project: { '_id': 1, name: 1, numPets: { $size: '$pets' } } }
]);

Это работает, однако это довольно медленно, и я спрашиваю себя, есть ли более эффективный способ выполнить запрос?

[обновление и обратная связь] Спасибо за ответы.Решения работают, но я, к сожалению, не вижу улучшения производительности по сравнению с приведенным выше запросом.Очевидно, что MongoDB все еще нужно сканировать всю коллекцию питомцев.Я надеялся, что индекс owner (который присутствует) в коллекции pets можно каким-то образом использовать для получения только количества (не нужно прикасаться к домашним животным документам), но, похоже, это не так.

Существуют ли другие идеи или решения для очень быстрого извлечения «счетчика домашних животных» помимо явного сохранения счета в документах владельца?

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Вы можете попробовать ниже агрегации

db.owners.aggregate([
  { "$lookup": {
    "from": "pets",
    "let": { "ownerId": "$_id" },
    "pipeline": [
      { "$match": { "$expr": { "$eq": [ "$$ownerId", "$owner" ] }}},
      { "$count": "count" }
    ],
    "as": "numPets"
  }},
  { "$project": {
    "_id": 1,
    "name": 1,
    "numPets": { "$ifNull": [{ "$arrayElemAt": ["$numPets.count", 0] }, 0]}
  }}
])
0 голосов
/ 25 сентября 2018

В MongoDB 3.6 вы можете создавать пользовательский $ lookup конвейер и считать вместо целых pets документов, попробуйте:

db.owners.aggregate([
    {
        $lookup: {
            from: "pets",
            let: { ownerId: "$_id" },
            pipeline: [
                { $match: { $expr: { $eq: [ "$$ownerId", "$owner" ] } } },
                { $count: "count" }
            ],
            as: "numPets"
        }
    },
    {
        $unwind: "$numPets"
    }
])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...