filter - query - MongoDB: filtrado del contenido de una matriz interna en un conjunto de resultados
project mongodb (5)
Soy nuevo usando MongoDB, y no sé cómo resolver el siguiente problema:
Tengo una colección de documentos como este:
{
"URL": "www.stackoverflow.com",
"TAGS": [
{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}
]
}
Antes que nada, quería todas las URL que tienen todas las etiquetas en una lista. He resuelto esto haciendo quering:
db.links.find( { "Tags.Name" : { $all: ["question","answers"] } } );
Pero esta consulta devuelve todo el documento correcto, inscrito solo en el documento correcto con solo las etiquetas que he solicitado.
El resultado que estoy buscando es:
{
"URL": "www.stackoverflow.com",
"TAGS": [{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5}]
}
y no:
{
"URL": "www.stackoverflow.com",
"TAGS": [{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}]
}
Porque solo pedí las etiquetas ["pregunta", "respuestas"].
Pensé en utilizar MapReduce o analizar el conjunto de resultados, pero no sé si es la forma correcta de resolver el problema. Tal vez haya una función integrada que lo resuelva de manera más eficiente.
¡Gracias!
En términos generales, cualquier operación de find()
en MongoDB devuelve todos los documentos que coinciden con la consulta y todos los documentos se recuperan en su totalidad. Si solo quiere una sección específica de un documento, entonces tiene que hacer ese procesamiento en el lado del cliente.
Esta es una diferencia fundamental entre las bases de datos de documentos y SQL. Normalmente, en una base de datos de documentos, una consulta devuelve todos los documentos que coinciden, mientras que en una base de datos SQL puede elegir devolver solo partes de la tabla. A menos, por supuesto, como usted dice que hace un MapReduce, pero que parece un exceso para su caso de uso.
No para desalentar el uso de MongoDB, pero cualquier proyecto en el que trabaje considere si las bases de datos NoSQL realmente se ajustan a la factura (si cumplen un requisito que SQL no puede) o si aún sería mejor utilizar una base de datos SQL tradicional.
Es posible suprimir las teclas y los elementos de la matriz en el documento devuelto, pero no de la manera que desee.
En su ejemplo, puede suprimir la clave URL con la siguiente consulta, que usa el segundo argumento para encontrar ():
db.links.find({"TAGS.NAME" : {$all : ["question","answer"]}}, {"URL" : 0})
Sin embargo, no creo que sea posible suprimir miembros individuales de una matriz en el lado del servidor con find () en función de qué miembros de la matriz se especificaron con $ all.
Puede usar $ slice para devolver solo ciertos miembros de una matriz, pero está basado en posición. Por ejemplo,
{$slice : [1, 2]}
omite el primer elemento de la matriz y regresa a los siguientes dos.
Gracias Robert. Me di cuenta de que la función que estoy buscando no está implementada en este momento. Aquí está el enlace del problema . Espero que el MongoDB lo implemente en poco tiempo. ¡Gracias!
Puede usar el marco de agregación de MongoDB
.
Si tiene un documento en su colección como;
{
"URL": "www..com",
"TAGS": [
{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}
]
}
y desea filtrar algunos elementos de la matriz, puede usar la muestra de agregación;
db.sof_table.aggregate
([
{$unwind:''$TAGS''},
{$match:{''TAGS.NAME'':{$in:[''answer'',''question'']}}},
{$group:{_id:''$URL'',TAGS:{$push:''$TAGS''}}}
])
Esto resultará;
{
"result" : [
{
"_id" : "www..com",
"TAGS" : [
{
"NAME" : "question",
"VOTES" : 3
},
{
"NAME" : "answer",
"VOTES" : 5
}
]
}
],
"ok" : 1
}
como resultado esperado
Esto podría ayudarte.
El operador de proyección $ elemMatch toma un argumento de condición explícita. Esto le permite proyectar basándose en una condición que no está en la consulta, o si necesita proyectar en base a múltiples campos en los documentos incrustados de la matriz. **
https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/