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

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

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

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

Ответ 1

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

Это запросы для документов, где headers равно { From: ... }, т.е. не содержит других полей.


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

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


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

Ответ 2

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

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

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


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

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});

Ответ 3

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

Сначала я вставил только два объекта в коллекцию, а именно: 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

Надеюсь, что это объяснение с примером сделает кого-то более ясным в поиске запроса с поддокументами.