Tengo registros primarios y secundarios que son idénticos en los campos. Sin embargo, ciertos campos solo se establecen en un nivel principal.
El campo principal establecido en una cadena vacía ("") significa que el registro es principal. Los otros registros tienen un conjunto de valores que apuntan al padre, por lo que pueden considerarse registros secundarios.
Ahora considere los siguientes registros:
{"_id": 1, parent: "", "pValue": ["a", "b", "c"], fieldA: 2}, {"_id": 2, parent: 1, "pValue": [], fieldA: 2}, {"_id": 3, parent: 1, "pValue": [], fieldA: 2}, {"_id": 4, parent: "", "pValue": ["d"], fieldA: 9}, {"_id": 5, parent: 4, "pValue": [], fieldA:2}, {"_id": 6, parent: 4,"pValue": [], fieldA: 9}Los registros anteriores contienen dos padres, cada uno con 2 registros secundarios asociados. La consulta que estoy tratando de realizar implica hacer coincidir dos parámetros dados. Primero un valor en pValue. Una vez que obtenga todos los padres con ese pValue específico en su matriz. Luego quiero hacer coincidir ese padre Y todos sus registros secundarios asociados con el valor de fieldA.
Entonces, si se me da pValue="d" y fieldA=9, quiero los siguientes registros dentro del cursor:
{"_id": 4, parent: "", "pValue": ["d"], fieldA: 9} {"_id": 6, parent: 4, "pValue": [],fieldA: 9}Notas:
Mi intento:
cursor=self.pCollection.aggregate([ { "$match": {"pValue":{"$in":[pCheck]}}, { "$graphLookup" : { "from": "pCollection", "startWith": "$_id", "connectFromField": "_id", "connectToField": "parent", "as" : "children" } }])Luego me quedé atascado con todos los niños asociados con el padre como una matriz sin saber cómo envolverlos.
Debe seleccionar los documentos que coincidan con sus criterios de consulta mediante $match y filtrar la matriz "secundaria" para agregar una etapa $addFields .
Después $filter , puede usar arrayElemAt para asignar ese elemento a un campo.
{ "$match": { "fieldA": 9, "children.fieldA": 9 } }, { "$addFields": { "children": { "$arrayElemAt": [ { "$filter": { "input": "$children", "as": "child", "cond": { "$eq": [ "$$child.fieldA", 9 ] } }}, 0 ] } }}Su consulta arrojará algo como esto:
{ "_id" : 4, "parent" : "", "pValue" : [ "d" ], "fieldA" : 9, "children" : { "_id" : 6, "parent" : 4, "pValue" : [ ], "fieldA" : 9 } }Sin embargo, con un poco de fe, puede obtener el resultado esperado.
db.collection.aggregate([ { "$graphLookup": { "from": "collection", "startWith": "$_id", "connectFromField": "_id", "connectToField": "parent", "as" : "children" }}, { "$match": { "fieldA": 9, "children.fieldA": 9 } }, { "$addFields": { "children": { "$arrayElemAt": [ { "$filter": { "input": "$children", "as": "child", "cond": { "$eq": [ "$$child.fieldA", 9 ] } }}, 0 ] } }}, { "$project": { "children": [ "$children", { "_id": "$_id", "parent": "$parent", "pValue": "$pValue", "fieldA": "$fieldA" } ] }}, { "$unwind": "$children" }, { "$replaceRoot": { "newRoot": "$children" } } ])que produce algo como esto:
{ "_id" : 6, "parent" : 4, "pValue" : [ ], "fieldA" : 9 } { "_id" : 4, "parent" : "", "pValue" : [ "d" ], "fieldA" : 9 }Francamente, no creo que esto sea algo que debas hacer en tu aplicación. La primera opción es algo con lo que puedes y debes vivir.
Si realmente necesita esto, le sugiero quecree una vista y consulte la vista en su aplicación.
Al invertir la consulta y hacer coincidir primero el campo A y luego hacer una búsqueda gráfica desde el padre--> _id (por lo tanto, asignar el padre al hijo), pude asociar a los hijos para que tuvieran el campo A de sus padres.
Esta es la consulta con la que terminé:
cursor=self.collection.aggregate([ { "$match": {"fieldA":9}}, { "$graphLookup" : { "from": "collection", "startWith": "$parent", "connectFromField": "parent", "connectToField": "_id", "as" : "parents" } }, { "$project" : { "pValue": { "$cond":[ {"$ne":["$pValue",[]]},"$pValue", {"$let":{"vars": {"obj": {"$arrayElemAt": ["$parents", 0]}}, "in": "$$obj.pValue"}}]} } }, { "$match": {"pValue":{"$in":["d"]}}} ])