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: "[email protected]" } } ).count()
0
db.messages.find( { 'headers.From': "[email protected]" }  ).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ę?

Edmondo1984
źródło

Odpowiedzi:

419

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

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


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

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


Dokumenty z notacją kropkową

shx2
źródło
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'
    }
});
Edmondo1984
źródło
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" : "[email protected]"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "[email protected]",
        "To" : "[email protected]"
    }
}
>

Jaki jest wynik zapytania: db.messages.find({headers: {From: "[email protected]"} }).count()

Powinno być jedno, ponieważ zapytania dotyczące dokumentów, w których jest headersrówny obiektowi {From: "[email protected]"}, 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: "[email protected]", From: "[email protected]"}  }).count()
0

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

> db.messages.find({headers: {From: "[email protected]", To: "[email protected]"}  }).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': "[email protected]" }  ).count()
2

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

krishna Prasad
źródło