Как запросить вложенные объекты?

У меня проблема при запросе mongoDB с нотацией вложенных объектов:

db.messages.find( { headers : { From: "[email protected]" } } ).count()
0
db.messages.find( { 'headers.From': "[email protected]" }  ).count()
5

Я не понимаю, что делаю неправильно. Я ожидаю, что нотация вложенных объектов вернет тот же результат, что и запрос с точечной нотацией. Где я не прав?


person Edmondo1984    schedule 14.04.2013    source источник


Ответы (3)


db.messages.find( { headers : { From: "[email protected]" } } )

Запрашивает документы, в которых headers равно { From: ... }, т. Е. Не содержит других полей.


db.messages.find( { 'headers.From': "[email protected]" } )

Это проверяет только поле headers.From, на которое не влияют другие поля, содержащиеся в headers или отсутствующие в нем.


Документы с точечной нотацией

person shx2    schedule 14.04.2013
comment
Есть ли способ сделать это без кавычек вокруг заголовков. - person trysis; 01.05.2014
comment
Не знаю, просто интересно, и подумал, что иногда это может быть полезно. - person trysis; 02.05.2014
comment
@trysis - На практике я обнаружил, что объявления встроенных объектов (таких как примеры в документации mongo [ose] и в большинстве других примеров) просто недостаточно в реальном мире. Я выработал привычку создавать объекты «условия» и «поля», с которыми я могу делать что-то вроде conditions['some.path'] = 'value' в моей бизнес-логике, а затем выполнять один запрос в конце: find(conditions, fields, callback); - person Ryan Wheale; 21.05.2014
comment
Что, если предположим, что у меня есть ключ, содержащий domain.com, это не сработает: domains.domain.com. Есть ли обходной путь для этого сценария (без изменения domain.com на что-то другое, например domain_com)? - person Rens Tillmann; 11.06.2020
comment
Отвечая на мой собственный комментарий, лучше всего избегать использования точек полностью в ваших ключах. В своем решении я полностью отказался от доменов, являющихся ключами, и вместо этого создал срез / массив. - person Rens Tillmann; 11.06.2020

Два механизма запросов работают по-разному, как это предлагается в документации в разделе Поддокументы:

Если поле содержит внедренный документ (т. Е. вложенный документ), вы можете либо указать весь вложенный документ как значение поля, либо «добраться до» вложенный документ с использованием точечной нотации, чтобы указать значения для отдельных полей в вложенном документе:

Равенство совпадает с вложенными документами. Выбирайте документы, если вложенный документ точно соответствует указанному вложенному документу, включая порядок полей.


В следующем примере запрос соответствует всем документам, в которых значение производителя поля является вложенным документом, содержащим только поле company со значением 'ABC123' и поле address со значением '123 Street' в точном порядке:

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});
person Edmondo1984    schedule 14.04.2013
comment
Я сходил с ума. Это кажется мне довольно непоследовательным, потому что при запросе объектов его прямые свойства могут быть сопоставлены в любом порядке. - person Capaj; 13.11.2015

Поскольку существует большая путаница с запросами коллекции MongoDB с субдокументами, я подумал, что стоит объяснить приведенные выше ответы на примерах:

Сначала я вставил в коллекцию только два объекта, а именно: message как:

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "[email protected]"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "[email protected]",
        "To" : "[email protected]"
    }
}
>

Итак, каков результат запроса: db.messages.find({headers: {From: "[email protected]"} }).count()

Он должен быть один, потому что эти запросы для документов, где headers равно объекту {From: "[email protected]"}, т. Е. Не содержат других полей, или мы должны указать весь вложенный документ как значение поля.

Итак, согласно ответу @ Edmondo1984

Равенство совпадает с вложенными документами. Выберите документы, если вложенный документ соответствует точно указанному вложенному документу, включая порядок полей.

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

> db.messages.find({headers: {To: "[email protected]", From: "[email protected]"}  }).count()
0

А что, если мы изменим порядок From и To, т.е. такой же, как субдокументы вторых документов?

> db.messages.find({headers: {From: "[email protected]", To: "[email protected]"}  }).count()
1

поэтому он соответствует точно указанному вложенному документу, включая порядок полей.

Я думаю, что использование точечного оператора очень понятно для всех. Давайте посмотрим на результат запроса ниже:

> db.messages.find( { 'headers.From': "[email protected]" }  ).count()
2

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

person krishna Prasad    schedule 05.05.2019