2013-06-25 19 views
32

Poprosiłem o to jako komentarz do pytania another, a także opublikowałem question na mongodb-user. Brak odpowiedzi do tej pory, więc uciekam się do zadawania osobnego pytania.Kwerenda zagnieżdżonych zapytań MongoDB

W documentation stany:

Jeśli pole posiada tablicę, a następnie $ w operator wybiera dokumenty których pole trzyma tablicę, która zawiera co najmniej jeden element, który odpowiada wartości w określonej tablicy (np itp)

Używam:

mongod --version: 
db version v2.2.2, pdfile version 4.5 
Thu May 30 12:19:12 git version: d1b43b61a5308c4ad0679d34b262c5af9d664267 

mongo --version: 
MongoDB shell version: 2.0.4 

W MongoDB skorupy:

db.nested.insert({'level1': {'level2': [['item00', 'item01'], ['item10', 'item11']]}}) 

Oto lista pytań, które powinny działać zgodnie z dokumentacją, a wyniki, które produkują:

Dlaczego to nie działa?

> db.nested.findOne({'level1.level2.0': 'item00'}) 
null 

Dlaczego potrzebuję $ all?

> db.nested.findOne({'level1.level2.0': {'$all': ['item00']}}) 
{ 
    "_id" : ObjectId("51a7a4c0909dfd8872f52ed7"), 
    "level1" : { 
     "level2" : [ 
      [ 
       "item00", 
       "item01" 
      ], 
      [ 
       "item10", 
       "item11" 
      ] 
     ] 
    } 
} 

Powinien działać co najmniej jeden z poniższych elementów, prawda?

> db.nested.findOne({'level1.level2.0': {'$in': ['item00']}}) 
null 

> db.nested.findOne({'level1.level2': {'$in': ['item00']}}) 
null 

Jakieś pomysły? Rozważamy rezygnację z MongoDB, jeśli składnia zapytań nie działa zgodnie z reklamą.

Dzięki!

Odpowiedz

6

Użyj zagnieżdżonego elemMatch do wyszukiwania zagnieżdżonych poziomów w tablicach.

Szczegóły here.

4

Krótka odpowiedź: $ in jest dla pola o pojedynczej wartości, a $ all dla tablic.

Po pierwsze, db.nested.findOne({'level1.level2.0': 'item00'}) nie działa, ponieważ level1.level2.0 przechowuje tablicę i próbujesz ją porównać z jedną wartością.

Teraz, db.nested.findOne({'level1.level2.0': {'$in': ['item00']}}) nie działa z powodu podobnego powodu. $ in służy do porównywania pola z jedną wartością (masz tablicę) z kilkoma wartościami w tablicy (określonej w zapytaniu). $ in mówi: daj mi dokumenty, które mają to pole, której wartość jest zawarta w tej tablicy.

$ wszystko działa, ponieważ mówi: daj mi dokumenty, które mają to pole z kilkoma wartościami i wszystkie wartości tej tablicy (w zapytaniu) są zawarte w tym polu. (edytowane)

Może być trudno dostać ale wygląda na to, co mówi dokumentacja dla każdego:

$ wszystko wybiera dokumenty gdzie pole trzyma tablicę i zawiera wszystkie elementy(e.g. <value>, <value1>, etc.) w tablica.

$ w wybiera dokumenty, w których wartość pola równa się żadnej wartości w określonej tablicy (e.g. <value1>, <value2>, etc.)

nadzieję, że pomoże

+0

Dziękujemy za poświęcenie czasu na odpowiedź, ale niestety żadna z twoich odpowiedzi nie jest poprawna. Na stronie "Przeczytaj" podręcznika wyszukaj "Następująca operacja zwraca kursor do wszystkich dokumentów w kolekcji biosu, w której w polu tablicy zawiera element" UNIX ":" W odnośniku do dokumentacji w górnej części mojego pytania, możesz zobaczyć, że $ in powinno działać na polach zawierających tablice. Na koniec stwierdzenie "$ all działa, ponieważ ..." jest błędne: nie wszystkie wartości w polu muszą istnieć w zapytaniu, ale wszystkie wartości w zapytaniu muszą istnieć w polu dokumentu. – dgorur

+0

Dzięki za poprawkę w "$ wszystko działa, ponieważ ...". Więc mówisz, że $ in powinno działać dla tablic i dokumentacja tak mówi. Teraz jestem zaintrygowany. Zrobię kilka eksperymentów i zobaczę, czy się dowiem. Masz tutaj bardzo interesujące pytanie! – AntonioOtero

+0

Moje odkrycia przedstawiłem w innej odpowiedzi, mam nadzieję, że ci się przyda. – AntonioOtero

29

Po uruchomieniu kilka zapytań, doszedłem do wniosku, że $ in nie działa dla tablicy tablic.

Zamiast tego można użyć $elemMatch i będzie działać, ale to frustrujące, że dokumentacja MongoDB nie ostrzega o tym.

Stworzyłem ten dokument:

{ 
     "_id": "51cb12857124a215940cf2d4", 
     "level1": [ 
     [ 
      "item00", 
      "item01" 
     ], 
     [ 
      "item10", 
      "item11" 
     ] 
     ], 
     "items": [ 
     "item20", 
     "item21" 
     ] 
} 

Wskazówka, że ​​pole "przedmioty" jest tablicą ciągów i ta kwerenda działa idealnie:

db.nested.findOne({"items":{"$in":["item20"]} }) 

Teraz "level1.0" jest również tablica łańcuchów, jedyną różnicą jest to, że znajduje się wewnątrz innej tablicy. Ta kwerenda powinny działać, ale nie jest:

db.nested.findOne({"level1.0":{"$in":["item00"]} }) 

Jedynym sposobem, aby uzyskać wynik jest za pomocą $ elemMatch:

db.nested.findOne({"level1":{"$elemMatch":{"$in":['item00']}} }) 

Więc $elemMatch rozwiązuje problem, ale prawdziwym rozwiązaniem jest aktualizacja dokumentacji MongoDB za stwierdza, że ​​$in nie działa dla tablic tablic. Być może powinieneś przesłać prośbę do 10gen.

+1

Hehe. Teraz mówisz. Użyłem tego obejścia dla niektórych zapytań, ale wtedy: co jeśli chcę użyć $ nin? Pojawia się ten sam rodzaj tajemniczego zachowania, a potem zaczęliśmy wątpić we wszystkie wyniki zapytań, które otrzymywaliśmy. Ponadto dziękuję za określenie "tablica tablic". – dgorur

Powiązane problemy