Mongodb: найти документы с массивом, где все элементы существуют в массиве запросов, но массив документов может быть меньше

У меня есть коллекция в моей базе данных, где большинство документов имеют поля массива. Эти массивы содержат ровно 2 элемента. Теперь я хочу найти все документы, в которых все эти элементы массива являются элементами моего массива запросов.

Примеры документов:

{ a:["1","2"] },
{ a:["2","3"] },
{ a:["1","3"] },
{ a:["1","4"] }

Массив запросов:

["1","2","3"]

Запрос должен найти первые 3 документа, но не последний, так как в моем массиве запросов нет "4".

Ожидаемый результат:

{ a:["1","2"] },
{ a:["2","3"] },
{ a:["1","3"] }

Ждем полезного ответа:).

3 ответа

Решение

Поскольку размер статический, вы можете просто проверить, что оба элемента находятся в [1,2,3];

db.test.find(
  { $and: [ { "a.0": {$in: ["1","2","3"] } },
            { "a.1": {$in: ["1","2","3"] } } ] },
  { _id: 0, a: 1 }
)

>>> { "a" : [ "1", "2" ] }
>>> { "a" : [ "2", "3" ] }
>>> { "a" : [ "1", "3" ] }

РЕДАКТИРОВАТЬ: Делать это динамически немного сложнее, я не могу придумать способ без структуры агрегации. Просто посчитайте совпадения как 0 и не совпадения как 1, и, наконец, удалите все группы, которые имеют сумму!= 0;

db.test.aggregate(
  { $unwind: "$a" },
  { $group: { _id: "$_id", 
              a: { $push: "$a" },
              fail: { $sum: {$cond: { if: { $or: [ { $eq:["$a", "1"] },
                                                   { $eq:["$a", "2"] },
                                                   { $eq:["$a", "3"] }]
                                          },
                                      then: 0,
                                      else: 1 } } } } },
  { $match: { fail: 0 } },
  { $project:{ _id: 0, a: 1 } } 
)

>>> { "a" : [ "1", "3" ] }
>>> { "a" : [ "2", "3" ] }
>>> { "a" : [ "1", "2" ] }

Я также думаю, что это невозможно без структуры агрегации (если количество элементов является динамическим). Но я нашел более универсальный способ сделать это:

db.tests.aggregate({
  $redact: {
    $cond: {
      if: {$eq: [ {$setIsSubset: [ '$a', [ "1", "2", "3" ] ]}]},
      then: '$$KEEP',
      else: '$$PRUNE'
    }
  }
})

Я считаю, что ответом на вашу проблему является использование

$ в

(из документов:)

Рассмотрим следующий пример:

db.inventory.find ({qty: {$in: [5, 15]}})

Этот запрос выбирает все документы в инвентаре, где значение поля qty равно 5 или 15. Хотя этот запрос можно выразить с помощью оператора $ или, выберите оператор $in вместо оператора $ или при выполнении проверок на равенство поле.

Вы также можете делать более сложные вещи, используя массивы. Оформить заказ: http://docs.mongodb.org/manual/reference/operator/query/in/

Другие вопросы по тегам