Поиск MongoDB во встроенных документах

Используя пример, найденный по адресу:

https://docs.mongodb.com/manual/tutorial/query-array-of-documents/

Наличие:

db.inventory.insertMany( [
   { item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
   { item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
   { item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
   { item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);

и позже запрос:

db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )

возвращает набор документов со складом = А и кол-во = 5 в поддокументе "на складе"

Но запрос только для тех, которые содержат {склад: "A"}, не возвращает никакого результата

db.inventory.find( { "instock": { warehouse: "A" } } )

Теперь, изменив это на:

db.inventory.find( { "instock.warehouse": "A" })

работает

Разве они не должны быть одинаковыми? Что-нибудь о семантике?

С другой стороны, как правильно найти значение поля, которое находится в списке вложенных документов внутри другого списка вложенных документов (встроенных или встроенных)

Спасибо !


person Nelson La Rocca    schedule 14.04.2018    source источник


Ответы (1)


Когда вы нажимаете запрос: db.inventory.find( { "instock": { warehouse: "A" } } ) Он проверяет документы, в которых instock массив имеет только одно поле под ним. В этом случае это просто действует как проверка $eq. Вот почему вы получаете нулевой результат.

С другой стороны, у вас есть документы, в которых присутствуют как warehouse: "A", так и qty: 5.

Вот почему ваш второй запрос: db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } ) возвращает результаты.

Третий запрос: db.inventory.find( { "instock.warehouse": "A" }) — это правильный способ доступа к полям внутри встроенных документов.

Вместо этого запроса: db.inventory.find( { "instock": { warehouse: "A" } } )

Вы также можете использовать $elemMatch для доступа к полям внутри массива документов. db.inventory.find({ "instock": {$elemMatch:{warehouse: "A"} }})

person Rahul Raj    schedule 14.04.2018
comment
Спасибо, Рахул, за четкий ответ. использование $elemMatch означает потерю производительности? предположим, у меня есть массив вложенных документов, встроенный в массив вложенных документов в документе, как запросить идентификатор вложенного документа? - person Nelson La Rocca; 14.04.2018
comment
$elemMatch соответствуют условиям в одном и том же вложенном документе, а запись через точку соответствует условиям во всех вложенных документах. Поэтому, если вы хотите проверить, присутствуют ли в конкретном вложенном документе как warehouse: "A", так и qty: 5, вам нужно использовать $elemMatch. Если вместо этого вы используете точечную нотацию, будут проверены все документы, которые удовлетворяют условию. Таким образом, проверка не ограничивается одним вложенным документом. Надеюсь, ты понял. - person Rahul Raj; 14.04.2018
comment
@NelsonLaRocca это будет что-то вроде "a.b":{$elemMatch:{c:"test", d:"test"}} - person Rahul Raj; 14.04.2018
comment
Большое спасибо Рахул. Я думаю, что MongoDB следует углубиться в свои документы по этой теме. Спасибо еще раз. - person Nelson La Rocca; 14.04.2018