2011-02-11 16 views
19

Mam zapytanie poniżej. Chcę uzyskać pozycje od 4 do 6, więc tylko wartość: 1 powinna być zgodna, ponieważ ma wartość 5 na b.

> db.test.find({ b : { $gt : 4 }, b: {$lt : 6}}); 
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> 

Czy ktoś może powiedzieć, dlaczego a: 2 pasuje do tego zapytania? Naprawdę nie rozumiem, dlaczego jest zwracana.

Próbowałem również, co zostało określone w tutorialu ale id nie wydają się działać:

> db.test.find({ b : { $gt : 4, $lt : 6}}); 
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> 

i ten, aby uniknąć wszelkich nieporozumień dotyczących GT/GTE

> db.test.find({b: {$gt: 4.5, $lt: 5.5}}); 
{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d54d0074364000000004332"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> 

tylko: 1 powinien zostać zwrócony.

Jak sugeruje, dałem $ elemMatch spróbować, ale nie wydaje się do pracy albo (objectIds są różne, bo jestem na innym komputerze)

> db.test.find(); 
{ "_id" : ObjectId("4d5a24a5e82e00000000433f"), "a" : 1, "b" : [ 2, 3, 4, 5 ] } 
{ "_id" : ObjectId("4d5a24bbe82e000000004340"), "a" : 2, "b" : [ 2, 4, 6, 8 ] } 
> db.test.find({b: {$elemMatch: {$gt : 4, $lt: 6 }}}); 
> 

Żadne dokumenty zostały zwrócone.

+0

Właściwie oba dokumenty powinny być zwrócone, kwestia oznacza „daj mi wszystkie dokumenty gdzie' B' ma wartość, która wynosi od 4 do 6”, a to jest spełnione według obu dokumentów. Czy możesz dokładniej wyjaśnić, o co ma zapytać? Dlaczego powinienem znaleźć pierwszy dokument, ale nie drugi? – Theo

+0

Tak jak powiedziałeś powyżej, chcę wszystkich dokumentów, które mają ab między 4 a 6. Tylko a: 1 spełnia to (nie obie), ponieważ a: 2 nie zawiera żadnych wartości między 4 a 6 (używając gt i lt wyklucz 4 i 6 sami, gdzie gte i lte mogliby je uwzględnić). Wypróbowałem inne zapytanie (zobacz edytowane pytanie), które jest bardziej przejrzyste i nadal nie działa poprawnie ... – paullb

+1

Widzę, co masz na myśli teraz, myślałem o tym jako o zasięgu (a zakresy są zazwyczaj zawarte w pierwszym elemencie) , ale oczywiście nie jest, jest to ścisłe mniej niż i większe niż. Usunąłem odpowiedź, ponieważ teraz jest jasne, że była ona błędna. – Theo

Odpowiedz

51

To naprawdę mylący temat. Pracuję w 10gen i musiałem poświęcić chwilę na owijanie głowy wokół;)

Zobaczmy, jak silnik zapytań przetwarza to zapytanie.

Oto zapytanie ponownie:

> db.test.find({ b : { $gt : 4, $lt : 6}}); 

Kiedy robi się do rekordu, który wydaje się, że nie powinien pasować ...

{ "_id" : ObjectId("4d54cff54364000000004331"), "a" : 1, "b" : [ 2, 4, 6, 8 ] } 

Mecz nie jest wykonywane przed każdym elementem array, ale raczej w stosunku do tablicy jako całości.

Porównanie odbywa się w trzech etapach:

Krok 1 Znajdź wszystkie dokumenty, w których b ma wartość większą niż 4

b: [2,4,6,8] pasuje bo 6 & 8 jest większa niż 4

Etap 2 Znajdź wszystkie dokumenty, w których b ma wartość mniejszą niż 6

b: [2,4,6,8] dopasowania ES ponieważ 2 & 4 jest mniejsza niż 6

Etap 3 Znajdź zbiór dokumentów dopasowane zarówno w etapie 1 & 2.

Dokument z b: [2,4,6,8] pasuje oba kroki 1 & 2, więc jest zwracany jako mecz. Zwróć uwagę, że wyniki są również zdublowane w tym kroku, więc ten sam dokument nie zostanie zwrócony dwukrotnie.

Jeśli chcesz, aby zapytanie było stosowane do poszczególnych elementów tablicy, a nie do tablicy jako całości, możesz użyć operatora $ elemMatch. Na przykład

> db.temp.find({b: {$elemMatch: {$gt: 4, $lt: 5}}}) 
> db.temp.find({b: {$elemMatch: {$gte: 4, $lt: 5}}}) 
    { "_id" : ObjectId("4d558b6f4f0b1e2141b66660"), "b" : [ 2, 3, 4, 5, 6 ] } 
+0

Dzięki, Jared, za dobrze ułożoną odpowiedź. Jednak po wypróbowaniu go to nie działa. (Próbowałem "db.test.find ({b: {$ elemMatch: {$ gt: 4, $ lt: 6}}})", jak opisałeś. (Szczegóły można znaleźć w edytowanym pytaniu) Czy możesz rzucić jakiekolwiek światło na tym? – paullb

+0

Dziwne. To działa dla mnie. > db.array2.save ({b: [2,3,4,5]}) > db.array2.save ({b: [2,4, 6,8]}) > db.array2.find ({b: {$ elemMatch: {$ gt: 4, $ lt: 6}}}) {"_id": ObjectId ("4d5a9268ec5855af36625ed6"), "b ": [2, 3, 4, 5]} > Jakiej wersji MongoDB używasz? $ ElemMatch został dodany do wersji 1.3.1, więc jeśli nadal używasz wersji 1.2, to nie zadziała. – jared

+0

Nie działa. po prostu kopiuj i wklej swoje zapytania (wstaw, a następnie zapytaj) Mam 1.6.5 Wygląda na to, że może to być błąd: http://jira.mongodb.org/browse/SERVER-1264 – paullb

-9

Ponieważ nie sprawdzono dokumentacji.

Zobacz

http://www.mongodb.org/display/DOCS/Advanced+Queries

i sprawdzić "zakresach" na stronie.

Ani to poprawna składnia zapytań (por przeciwko przykład)

ani robi swoje „dlaczego: 2” część pytania żadnego sensu, ponieważ „a” nie jest zaangażowany w zapytaniu. Jeśli chcesz wyszukać: 1, musisz uwzględnić to w zapytaniu.

Należy pamiętać, że wszystkie klauzule zapytania są domyślnie połączone AND, chyba że użyje się operatora $ lub.

+0

Ponadto: jeśli interesuje Cię podzbiór pól: http://www.mongodb.org/display/DOCS/Retrieving+aubsubset+ofields –

+0

Dzięki za wskazanie przykładu zasięgu na tej stronie. Widziałem stronę, ale brakowało mi sekcji zasięgu. Składnia jest oczywiście poprawna, ponieważ kwerenda jest wykonywana, ale ja po prostu nie wykorzystuję współczynnika zasięgu. "Dlaczego a: 2" ma sens, ponieważ jednoznacznie identyfikuje każdy wiersz, nie musi brać udziału w kwerendzie. Powinienem również zwrócić uwagę, że jeśli klauzula jest interpretowana jako ORAZ, to moje zapytanie powinno nadal poprawnie przyjmować zakres. Dziękuję za link, ale nie za ogólne nieuprzejmość. – paullb

+0

Ogólne chamstwo? Przeczytaj samouczek. –

0
.find({$and:[ {b:{$gt:4}}, {b:{$lt:6}} ]}) 
+3

Nie. Składnia jako show w zaakceptowanej odpowiedzi jest poprawna i jest już operacją "i". Jest to lakoniczny i zły przykład czytelnej składni. –

4

$ GT

Syntax: {field: {$gt: value} } 

np

db.inventory.find({ qty: { $gt: 20 } }) 

$ LT

Syntax: {field: {$lt: value} } 

np

db.inventory.find({ qty: { $lt: 20 } }) 

EG2:

db.inventory.find({ qty : { $gt : 20, $lt : 60}}); 
Powiązane problemy