Mongo Query на нескольких полях суб-документа

Предположим, что у меня есть такая коллекция:

{ "arr" : [ { "name" : "a", "num" : 1 }, { "name" : "a", "num" : 2 } ] },
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "a", "num" : 2 } ] },
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "b", "num" : 2 } ] }

и я хочу найти все документы, которые arr содержат поддокумент с name= "b" и num= 2.

Если я сделаю такой запрос:

db.collection.find({
    $and: [
        { "arr.name": "b" },
        { "arr.num": 2 }
    ]
});

он вернет все документы в коллекции, потому что каждый из них содержит поддокумент с a name из "b" или num из 2.

Я также пробовал это:

db.collection.find({
    arr: [
        { "name": "b", "num": 2 }
    ]
});

который не вызывает никаких ошибок, но не возвращает никаких результатов.

Как вы запрашиваете несколько полей субдоку в MongoDB?

Ответ 1

На самом деле это оператор $elemMatch, хотя он часто используется неправильно. Он по существу выполняет условия запроса для каждого элемента "внутри" массива. Все аргументы MongoDB являются "и", если явно не указано иначе:

db.collection.find({ "arr": { "$elemMatch": { "name": "b", "num": 2  } } })

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

db.collection.find(
    { "arr": { "$elemMatch": { "name": "b", "num": 2  } } },
    { "arr.$": 1 }
)

Наконец, чтобы объяснить, почему ваша вторая попытка не работает, этот запрос:

db.collection.find({
    "arr": [
        { "name": "b", "num": 2 }
    ]
})

Ничего не соответствует, потому что нет фактического документа, где "arr" содержит особый элемент, точно соответствующий вашим условиям.

Ваш первый пример не удался..:

db.collection.find({
    $and: [
        { "arr.name": "b" },
        { "arr.num": 2 }
    ]
});

Поскольку существует несколько элементов массива, которые удовлетворяют условиям, и это не просто считается, что оба условия применяются к одному и тому же элементу. Это то, что добавляет $elemMatch, и когда вам нужно больше одного условия для соответствия, тогда вы его используете.