2011-02-11 15 views
19

tengo una consulta a continuación. Quiero obtener elementos entre 4 y 6, así que solo a: 1 debe coincidir porque tiene el valor 5 en 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 ] } 
> 

¿Alguien puede decir por qué a: 2 corresponde a esta consulta? Realmente no puedo ver por qué se devuelve.

También probé lo que se especifica en el tutorial, pero no parece id para trabajar:

> 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 ] } 
> 

Y éste para evitar cualquier confusión con respecto 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 ] } 
> 

sólo: 1 debe ser devuelto

Como se sugirió, le di $ elemMatch una oportunidad pero no parecen funcionar bien (ObjectID son diferentes porque estoy en un equipo diferente) fueron devueltos

> 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 }}}); 
> 

Ningún documento.

+0

En realidad, deben ser devueltos ambos documentos, la pregunta significa "dame todos los documentos en los que 'B' tiene un valor que oscila entre 4 y 6", y esto se cumple por ambos documentos. ¿Podría explicar con más detalle qué es lo que quiere consultar? ¿Por qué debería encontrarse el primer documento pero no el segundo? – Theo

+0

Como dices arriba, quiero todos los documentos que tienen ab entre 4 y 6. Solo a: 1 satisface esto (no ambos) porque a: 2 no contiene ningún valor entre 4 y 6 (usando gt y lt exclude 4 y 6 ellos mismos donde lo incluirían gte y lte). Intenté una consulta diferente (vea la pregunta editada) que es más clara y todavía no funciona correctamente ... – paullb

+1

Veo lo que quiere decir ahora, lo pensé como un rango (y los rangos suelen incluir el primer elemento) , pero por supuesto que no, es un estricto menor que y mayor que. He borrado mi respuesta ya que ahora está claro que fue incorrecta. – Theo

Respuesta

51

Este es un tema muy confuso. Yo trabajo en 10gen y tuve que pasar un tiempo envolver mi cabeza alrededor de ella;)

Vamos a caminar a través de cómo los procesos del motor consulta esta consulta.

Ésta es la consulta de nuevo:

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

Cuando se llega al registro que parece que no debe coincidir ...

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

El partido no se realiza contra cada elemento de la matriz, sino más bien contra la matriz como un todo.

La comparación se realiza en tres pasos:

Paso 1: Encontrar todos los documentos en donde b tiene un valor mayor que 4

b: [2,4,6,8] coincide porque 6 & 8 son mayores que 4

Paso 2: Encontrar todos los documentos en donde b tiene un valor de menos de 6

b: [2,4,6,8] partido es porque 2 & 4 son de menos de 6

Paso 3: Encontrar el conjunto de documentos que coincidan tanto en la etapa 1 & 2.

El documento con b: [2,4,6,8] emparejado ambos pasos 1 & 2 por lo que se devuelve como una coincidencia. Tenga en cuenta que los resultados también se desduplican en este paso, por lo que el mismo documento no se devolverá dos veces.

Si desea que su consulta se aplique a los elementos individuales de la matriz, en lugar de la matriz como un todo, puede usar el operador $ elemMatch. Por ejemplo

> 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

Gracias, Jared, por la respuesta bien presentada. Sin embargo, al intentarlo, parece que no funciona. (Probé "db.test.find ({b: {$ elemMatch: {$ gt: 4, $ lt: 6}}}"; "como usted describió. (Vea la pregunta editada para más detalles) ¿Puede arrojar algo de luz? en esto? – paullb

+0

Extraño. Funciona para mí. > 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]} > ¿Qué versión de MongoDB está usando? $ ElemMatch se agregó 1.3.1, por lo que si todavía está utilizando 1.2 no funcionará. – jared

+0

No Trabaja aquí. Solo copié y pegué tus consultas (inserta y luego consulta). Tengo 1.6.5. Parece que podría ser un error: http://jira.mongodb.org/browse/SERVER-1264 – paullb

-9

Por cuanto no comprueba la documentación.

Ver

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

y verificación para "rangos" en la página.

Ni es su sintaxis de consulta correcta (comparar con el ejemplo)

ni tampoco su "por qué una: 2" parte de la pregunta tiene sentido ya que 'a' no está involucrado en la consulta. Si desea buscar un: 1, debe incluirlo en su consulta.

Tenga en cuenta que todas las cláusulas de consulta son AND combinan de forma predeterminada a menos que utilice el $ u operador.

+0

Además: si está interesado en un subconjunto de campos: http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields –

+0

Gracias por señalar el ejemplo de rango en esa página. Había visto la página pero me perdí la sección de rango. La sintaxis es obviamente correcta ya que la consulta se ejecuta, pero simplemente no estoy aprovechando el factor de rango. El "por qué a: 2" tiene perfecto sentido ya que identifica de manera única cada fila, no necesita estar involucrado en la consulta. También debería señalar que si la cláusula se interpreta como AND, entonces mi consulta debería tomar el rango correc- tamente. Así que gracias por el enlace, pero no, gracias por la rudeza general. – paullb

+0

¿Rudeza general? Por favor, mira leer el tutorial. –

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

No. La sintaxis como se muestra en la respuesta aceptada es correcta y ya es una operación "y". Esto es escueto y un mal ejemplo de sintaxis legible. –

4

$ gt

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

por ejemplo:

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

$ lt

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

por ejemplo:

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

EG2:

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