Jak zapytać o zagnieżdżone obiekty?


204

Mam problem podczas zapytania do mongoDB z notacją zagnieżdżonych obiektów:

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

Nie widzę, co robię źle. Oczekuję, że notacja zagnieżdżonego obiektu zwróci ten sam wynik, co zapytanie notacji kropkowej. Gdzie się mylę?

Odpowiedzi:


419

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

To zapytanie dotyczy dokumentów, których wartość headers jest równa { From: ... } , tzn. Nie zawiera innych pól.


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

To tylko wygląda na headers.Frompole, nie dotknięte przez innych dziedzinach zawarte lub brakuje, headers.


Dokumenty z notacją kropkową


Czy można to zrobić bez cudzysłowu wokół „headers.From”?
próbuje

Nie wiem, zastanawiam się i pomyślałem, że czasem może się przydać.
trysis

3
@trysis - W praktyce odkryłem, że deklarowanie obiektów wbudowanych (takich jak przykłady w dokumentach mongo [ose] i większość przykładów tam dostępnych) po prostu nie wystarcza w prawdziwym świecie. Rozwinąłem zwyczaj tworzenia obiektów „warunków” i „pól”, na których mogę robić rzeczy takie, jak conditions['some.path'] = 'value'w mojej logice biznesowej, a następnie uruchamiam jedno zapytanie na końcu:find(conditions, fields, callback);
Ryan Wheale

Co jeśli powiedzmy Mam klucz, który zawiera „domain.com”, to nie będzie działać: domains.domain.com. Czy istnieje jakieś obejście tego scenariusza (bez zmiany domain.com na coś innego, np. Domain_com)?
Rens Tillmann

1
Odpowiadając na mój komentarz, najlepiej unikać używania kropek w klawiszach. W moim rozwiązaniu całkowicie porzuciłem domeny będące kluczami i zamiast tego utworzyłem plasterek / tablicę.
Rens Tillmann

20

Dwa mechanizmy zapytań działają na różne sposoby, jak sugerowano w dokumentach w sekcji Subdocuments :

Gdy pole zawiera osadzony dokument (tj. Dokument podrzędny ), możesz albo podać cały dokument podrzędny jako wartość pola, albo „dotrzeć do” dokumentu podrzędnego za pomocą notacji kropkowej, aby określić wartości dla poszczególnych pól w dokumencie podrzędnym :

Dopasowania równości w dokumentach podrzędnych wybierają dokumenty, jeśli dokument podrzędny pasuje dokładnie do określonego dokumentu podrzędnego, w tym do kolejności pól.


W poniższym przykładzie zapytanie pasuje do wszystkich dokumentów, w których wartość producenta pola jest dokumentem podrzędnym zawierającym tylko pole companyz wartością 'ABC123'i pole addressz wartością '123 Street', w dokładnej kolejności:

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

8
Wariowałam. Wydaje mi się to dość niespójne, ponieważ przy wyszukiwaniu obiektów można dobrać bezpośrednie właściwości w dowolnej kolejności.
Capaj,

7

Ponieważ istnieje wiele nieporozumień dotyczących zapytań dotyczących kolekcji MongoDB z dokumentami podrzędnymi , pomyślałem, że warto wyjaśnić powyższe odpowiedzi przykładami:

Najpierw wstawiłem tylko dwa obiekty do kolekcji, mianowicie: 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"
    }
}
>

Jaki jest wynik zapytania: db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

Powinno być jedno, ponieważ zapytania dotyczące dokumentów, w których jest headersrówny obiektowi {From: "reservations@marriott.com"}, tzn. Nie zawiera innych pól, lub powinniśmy podać cały poddokument jako wartość pola.

Więc zgodnie z odpowiedzią z @ Edmondo1984

Dopasowania równości w dokumentach podrzędnych wybierają dokumenty, jeśli dokument podrzędny pasuje dokładnie do określonego dokumentu podrzędnego, w tym kolejności pól .

Z powyższych instrukcji, jaki powinien być wynik poniżej zapytania?

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

A co, jeśli zmienimy kolejność, Froma Towięc taką samą jak poddokumenty drugich dokumentów?

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

więc pasuje dokładnie do poddokumentu, w tym do kolejności pól .

Myślę, że użycie operatora kropki jest bardzo jasne dla każdego. Zobaczmy wynik poniższego zapytania:

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

Mam nadzieję, że wyjaśnienia powyższego przykładu sprawią, że ktoś będzie bardziej przejrzysty w wyszukiwaniu zapytań z pod-dokumentami .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.