Supongamos que tiene los siguientes documentos en mi colección:
{
"_id":ObjectId("562e7c594c12942f08fe4192"),
"shapes":[
{
"shape":"square",
"color":"blue"
},
{
"shape":"circle",
"color":"red"
}
]
},
{
"_id":ObjectId("562e7c594c12942f08fe4193"),
"shapes":[
{
"shape":"square",
"color":"black"
},
{
"shape":"circle",
"color":"green"
}
]
}
Hacer consulta:
db.test.find({"shapes.color": "red"}, {"shapes.color": 1})
O
db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})
Devuelve el documento coincidente (Documento 1) , pero siempre con TODOS los elementos de la matriz en shapes
:
{ "shapes":
[
{"shape": "square", "color": "blue"},
{"shape": "circle", "color": "red"}
]
}
Sin embargo, me gustaría obtener el documento (Documento 1) solo con la matriz que contiene color=red
:
{ "shapes":
[
{"shape": "circle", "color": "red"}
]
}
¿Cómo puedo hacer esto?
aggregate
.db.test.find({}, {shapes: {$elemMatch: {color: "red"}}});
El nuevo Marco de agregación en MongoDB 2.2+ proporciona una alternativa a Map / Reduce. El
$unwind
operador se puede utilizar para separar sushapes
matriz en una secuencia de documentos que pueden coincidir:Resultados en:
fuente
$elemMatch
es otra opción. De hecho, llegué aquí a través de una pregunta de Google Group donde $ elemMatch no funcionaría porque solo devuelve la primera coincidencia por documento.{ $project : { shapes : 1 } }
, lo que parecía funcionar y sería útil si los documentos adjuntos fueran grandes y solo quisiera ver losshapes
valores clave.Otra forma interesante es usar $ redact , que es una de las nuevas características de agregación de MongoDB 2.6 . Si está utilizando 2.6, no necesita un desenrollado $ que podría causar problemas de rendimiento si tiene matrices grandes.
$redact
"restringe el contenido de los documentos en función de la información almacenada en los propios documentos" . Por lo tanto, se ejecutará solo dentro del documento . Básicamente escanea su documento de arriba a abajo y verifica si coincide con suif
condición$cond
, si existe una coincidencia, mantendrá el contenido ($$DESCEND
) o eliminará ($$PRUNE
).En el ejemplo anterior, primero
$match
devuelve toda lashapes
matriz y $ redact la despoja al resultado esperado.Tenga en cuenta que
{$not:"$color"}
es necesario, porque también escaneará el documento superior, y si$redact
no encuentra uncolor
campo en el nivel superior, esto devolveráfalse
que podría eliminar todo el documento que no queremos.fuente
$match
como tu primera etapa agregadaEl parámetro del selector de campo está limitado a propiedades completas. No se puede usar para seleccionar parte de una matriz, solo toda la matriz. Intenté usar el operador posicional $ , pero eso no funcionó.
La forma más fácil es simplemente filtrar las formas en el cliente .
Si realmente necesita la salida correcta directamente de MongoDB, puede usar un mapa-reducir para filtrar las formas.
fuente
Es mejor que pueda consultar el elemento de matriz coincidente utilizando si
$slice
es útil devolver el objeto significativo en una matriz.$slice
es útil cuando conoce el índice del elemento, pero a veces desea cualquier elemento de matriz que coincida con sus criterios. Puede devolver el elemento coincidente con el$
operador.fuente
SALIDAS
fuente
La sintaxis para encontrar en mongodb es
y la segunda consulta que has escrito, que es
en esto ha utilizado el
$elemMatch
operador en la parte de consulta, mientras que si utiliza este operador en la parte de proyección, obtendrá el resultado deseado. Puede escribir su consulta comoEsto te dará el resultado deseado.
fuente
"shapes.color":"red"
en el parámetro de consulta (el primer parámetro del método find) no es necesario. Puede reemplazarlo{}
y obtener los mismos resultados.Gracias a JohnnyHK .
Aquí solo quiero agregar un uso más complejo.
fuente
Solo necesitas ejecutar la consulta
la salida de esta consulta es
como esperaba, dará el campo exacto de la matriz que coincide con el color: 'rojo'.
fuente
junto con $ project, será más apropiado que otros elementos acertados coincidan con otros elementos del documento.
fuente
Del mismo modo puedes encontrar para el múltiple
fuente
$match
para reducir el espacio, luego$filter
para mantener lo que desea, sobrescribiendo el campo de entrada (use la salida de$filter
on fieldshapes
para$project
volver a hacerloshapes
. Nota de estilo: mejor no usar el nombre del campo como elas
argumento porque eso puede llevar a confusión más adelante con$$shape
y$shape
. Prefierozz
como elas
campo porque realmente se destaca.fuente
Use la función de agregación y
$project
para obtener un campo de objeto específico en el documentoresultado:
fuente
Aunque la pregunta se hizo hace 9,6 años, esto ha sido de gran ayuda para muchas personas, siendo yo una de ellas. Gracias a todos por todas sus consultas, sugerencias y respuestas. Retomando una de las respuestas aquí ... Descubrí que el siguiente método también se puede utilizar para proyectar otros campos en el documento principal. Esto puede ser útil para alguien.
Para el siguiente documento, la necesidad era averiguar si un empleado (emp # 7839) tiene su historial de licencias establecido para el año 2020. El historial de licencias se implementa como un documento incrustado dentro del documento del Empleado principal.
fuente