Как создать оператор запроса "in" для нескольких полей? - PullRequest
2 голосов
/ 13 июня 2019

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

db.list.insert({ first: "apple", second: "banana" });
db.list.insert({ first: "apple", second: "tree" });
db.list.insert({ first: "orange", second: "tree" });
db.list.insert({ first: "medal", second: "sport" });

Я хочу запросить документы на основе этих двух полей и получать документы только при совпадении обоих полей.

Я пробовал следующий запрос

db.list.find(
  $or: [
     { first: 'apple', second: { $in: ['tree', 'banana']}},
     { first: 'orange', second: { $in: ['tree']}}
  ],
).limit(5);

и добавленные индексы для

{first: 1, second: 1}

В плане запроса он генерирует такое же количество планов, что и количество предикатов в запросе "или". Имеется около 2 миллионов документов, и если он не получает свои 5 документов в первом предикате, он выбирает все документы, соответствующие всем предикатам, и время ожидания запроса истекает. Есть ли другой эффективный способ сделать это?

1 Ответ

0 голосов
/ 14 июня 2019

Вы можете использовать $ facet , используя mongodb конвейер агрегации . Это обеспечит получение документов только один раз. Вот пример запроса

    db.list.aggregate([
    {
        $facet: {
            "condition_1": [
                {
                    "$match": { first: 'apple', second: { $in: ['tree', 'banana']}}
                },
                {
                    "limit": 5
                }
            ],
            "condition_2": [
                {
                    "$match": { first: 'orange', second: { $in: ['tree']}}
                },
                {
                    "limit": 5
                }
            ]
        }
    }
], {allowDiskUse: true})
...