Як запитувати вкладені об’єкти?


204

У мене виникає проблема під час запиту mongoDB із позначеннями вкладених об'єктів:

db.messages.find( { headers : { From: "reservations@marriott.com" } } ).count()
0
db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
5

Я не бачу, що я роблю неправильно. Я очікую, що вкладка вкладеного об'єкта поверне той самий результат, що і запит на позначення крапок. Де я помиляюся?

Відповіді:


419

db.messages.find( { headers : { From: "reservations@marriott.com" } } )

Цей запит для документів, де headers дорівнює { From: ... } , тобто не містить інших полів.


db.messages.find( { 'headers.From': "reservations@marriott.com" } )

Це тільки дивиться на headers.Fromполе, не порушені в інших областях , що містяться в, або відсутній, headers.


Документи з крапковими позначеннями


Чи є спосіб зробити це без лапок навколо "заголовків. Звідси"?
трис

Я не знаю, просто цікаво, і думав, що іноді може бути корисним.
трис

3
@trysis - На практиці я виявив, що декларування вбудованих об'єктів (як, наприклад, в документах mongo [ose], і в більшості прикладів там) просто не вистачає в реальному світі. У мене з'явилася звичка створювати об'єкти "умови" та "поля", на яких я можу робити такі речі, як conditions['some.path'] = 'value'у моїй бізнес-логіці, а потім виконувати єдиний запит наприкінці:find(conditions, fields, callback);
Райан Уіл,

Що робити , якщо , скажімо , у мене є ключ , який містить «domain.com», це не буде працювати: domains.domain.com. Чи є якесь вирішення цього сценарію (не змінюючи domain.com на щось інше, наприклад, domain_com)?
Rens Tillmann

1
Відповідаючи на власний коментар, найкраще уникати використання точок повністю у ваших клавішах. У своєму рішенні я повністю викреслив домени, які є ключами, і створив натомість фрагмент / масив.
Rens Tillmann

20

Два механізми запиту працюють по-різному, як це запропоновано в документах у розділі Піддокументи :

Коли поле містить вбудований документ (тобто піддокумент ), ви можете або вказати весь піддокумент як значення поля, або "дістатися до" піддокумента, використовуючи позначення крапок, щоб вказати значення для окремих полів піддокумента :

Збіги рівності в рамках піддокументів вибирають документи, якщо піддокумент відповідає точно вказаному піддокументації, включаючи порядок польових.


У наступному прикладі запит відповідає всім документам, де значенням виробника поля є піддокумент, який містить лише поле companyзі значенням 'ABC123'і поле addressзі значенням '123 Street'у точному порядку:

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

8
Я зійшов з розуму. Мені це здається досить непослідовним, тому що при запиті об’єктів його прямі властивості можна зіставити в будь-якому порядку.
Капай

7

Оскільки існує велика плутанина щодо запитів колекції MongoDB з піддокументами , я вважав, що варто пояснити вищезазначені відповіді на прикладах:

Спочатку я вставив у колекцію лише два об’єкти, а саме: messageas:

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "reservations@marriott.com"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "reservations@marriott.com",
        "To" : "kprasad.iitd@gmail.com"
    }
}
>

Отже, що є результатом запиту: db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

Він повинен бути одним, тому що ці запити для документів, де headersдорівнює об'єкту {From: "reservations@marriott.com"}, тобто не містять інших полів, або ми повинні вказати весь піддокумент як значення поля.

Так, відповідно до відповіді від @ Edmondo1984

Збіги рівності в піддокументах вибирають документи, якщо піддокумент відповідає точно вказаному піддокументу, включаючи порядок польових .

З наведених тверджень, яким повинен бути результат запиту нижче?

> db.messages.find({headers: {To: "kprasad.iitd@gmail.com", From: "reservations@marriott.com"}  }).count()
0

А що , якщо ми змінимо порядок Fromі Toто є такі ж , як піддокументами друге документів?

> db.messages.find({headers: {From: "reservations@marriott.com", To: "kprasad.iitd@gmail.com"}  }).count()
1

Таким чином, він відповідає точно вказаному піддокументу, включаючи порядок використання поля .

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

> db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).count()
2

Я сподіваюсь, що ці пояснення з наведеним вище прикладом зроблять комусь більшу зрозумілість щодо пошуку запиту з піддокументами .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.