¿Cómo consultar objetos anidados?

205

Tengo un problema al consultar mongoDB con notación de objetos anidados:

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

No puedo ver lo que estoy haciendo mal. Espero que la notación de objetos anidados devuelva el mismo resultado que la consulta de notación de puntos. Donde me equivoco

Edmondo1984
fuente

Respuestas:

419

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

Esto consulta documentos donde headers es igual { From: ... } , es decir, no contiene otros campos.


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

Esto solo mira el headers.Fromcampo, no afectado por otros campos contenidos o faltantes en headers.


Documentos de notación de puntos

shx2
fuente
¿Hay alguna manera de hacer esto sin las comillas alrededor de "encabezados. De"?
trysis
No sé, solo me pregunto, y pensé que a veces puede ser útil.
trysis
3
@trysis: en la práctica, descubrí que declarar objetos en línea (como los ejemplos en mongo [ose] docs, y en la mayoría de los ejemplos) simplemente no es suficiente en el mundo real. He desarrollado el hábito de crear objetos de 'condiciones' y 'campos' en los que puedo hacer cosas como conditions['some.path'] = 'value'en mi lógica de negocios, luego ejecuto una sola consulta al final:find(conditions, fields, callback);
Ryan Wheale
¿Y si vamos a decir que tengo una llave que contiene "domain.com", esto no funcionará: domains.domain.com. ¿Hay alguna solución para este escenario (sin alterar el dominio.com a otra cosa, por ejemplo, dominio_com)?
Rens Tillmann
1
Respondiendo a mi propio comentario, es mejor evitar el uso de puntos completamente en sus claves. En mi solución, abandoné completamente los dominios como claves, y en su lugar creé un segmento / matriz.
Rens Tillmann
20

Los dos mecanismos de consulta funcionan de diferentes maneras, como se sugiere en los documentos en la sección Subdocumentos :

Cuando el campo contiene un documento incrustado (es decir, subdocumento ), puede especificar todo el subdocumento como el valor de un campo, o "alcanzar" el subdocumento utilizando la notación de puntos, para especificar valores para campos individuales en el subdocumento :

La igualdad coincide con los subdocumentos para seleccionar documentos si el subdocumento coincide exactamente con el subdocumento especificado, incluido el orden de los campos.


En el siguiente ejemplo, la consulta coincide con todos los documentos donde el valor del productor de campo es un subdocumento que contiene solo el campo companycon el valor 'ABC123'y el campo addresscon el valor '123 Street', en el orden exacto:

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});
Edmondo1984
fuente
8
Me estaba volviendo loco. Esto me parece bastante inconsistente, porque cuando se consultan objetos, sus propiedades directas pueden coincidir en cualquier orden.
Capaj
7

Como hay mucha confusión sobre las consultas de la colección MongoDB con subdocumentos , pensé que valía la pena explicar las respuestas anteriores con ejemplos:

Primero, he insertado solo dos objetos en la colección, a saber: messagecomo:

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "[email protected]"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "[email protected]",
        "To" : "[email protected]"
    }
}
>

Entonces, ¿cuál es el resultado de la consulta: db.messages.find({headers: {From: "[email protected]"} }).count()

Debería ser uno porque estas consultas para documentos eran headersiguales al objeto {From: "[email protected]"}, es decir, no contiene otros campos o deberíamos especificar el subdocumento completo como el valor de un campo.

Entonces, según la respuesta de @ Edmondo1984

La igualdad coincide dentro de los subdocumentos seleccione documentos si el subdocumento coincide exactamente con el subdocumento especificado, incluido el orden de los campos .

De las declaraciones anteriores, ¿cuál debería ser el resultado de la consulta a continuación?

> db.messages.find({headers: {To: "[email protected]", From: "[email protected]"}  }).count()
0

¿Y qué pasa si cambiamos el orden Fromy, Toes decir, lo mismo que los subdocumentos de los segundos documentos?

> db.messages.find({headers: {From: "[email protected]", To: "[email protected]"}  }).count()
1

por lo tanto, coincide exactamente con el subdocumento especificado, incluido el orden de los campos .

Para usar el operador de punto, creo que es muy claro para todos. Veamos el resultado de la consulta a continuación:

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

Espero que estas explicaciones con el ejemplo anterior hagan que alguien sea más claro al buscar consultas con subdocumentos .

Krishna Prasad
fuente