Encontrar en doble nido Array MongoDB

Tengo esta colección en mongodb

{ "_id" : "777", "someKey" : "someValue", "someArray" : [ { "name" : "name1", "someNestedArray" : [ { "name" : "value" }, { "name" : "delete me" } ] } ] } 

Quiero encontrar el documento basado en someArray.someNestedArray.name, pero no puedo encontrar ningún enlace útil. Todos los resultados de la búsqueda sobre la actualización de la matriz anidada. Lo bash pero no devuelvo nada.

 db.mycollection.find({"someArray.$.someNestedArray":{"$elemMatch":{"name":"1"}}}) db.mycollection.find({"someArray.$.someNestedArray.$.name":"1"}) 

y algo más

¿Cómo puedo encontrar por elemento en la matriz anidada doble mongodb?

En el sentido más simple, esto simplemente sigue la forma básica de “notación de puntos” como la usa MongoDB. Eso funcionará independientemente de en qué miembro de la matriz se encuentre el miembro de la matriz interna, siempre que coincida con un valor:

 db.mycollection.find({ "someArray.someNestedArray.name": "value" }) 

Eso está bien para un valor de “campo único”, para hacer coincidir campos múltiples usaría $elemMatch :

 db.mycollection.find({ "someArray": { "$elemMatch": { "name": "name1", "someNestedArray": { "$elemMatch": { "name": "value", "otherField": 1 } } } } }) 

Eso coincide con el documento que contendría algo con un campo en esa “ruta” que coincida con el valor. Si pretendía “hacer coincidir y filtrar” el resultado para que solo se devolviera el elemento coincidente, esto no es posible con la proyección del operador posicional, como se cita :

Matrices anidadas

El operador $ posicional no se puede usar para consultas que atraviesan más de una matriz, como consultas que atraviesan matrices anidadas dentro de otras matrices, porque el reemplazo para $ placeholder es un valor único

MongoDB moderno

Podemos hacer esto aplicando $filter y $map aquí. El $map es realmente necesario porque la matriz “interna” puede cambiar como resultado del “filtrado”, y la matriz “externa” por supuesto no concuerda con las condiciones cuando se eliminó el “interno” de todos los elementos.

De nuevo, siguiendo el ejemplo de tener realmente varias propiedades para que coincidan dentro de cada conjunto:

 db.mycollection.aggregate([ { "$match": { "someArray": { "$elemMatch": { "name": "name1", "someNestedArray": { "$elemMatch": { "name": "value", "otherField": 1 } } } } }}, { "$addFields": { "someArray": { "$filter": { "input": { "$map": { "input": "$someArray", "as": "sa", "in": { "name": "$$sa.name", "someNestedArray": { "$filter": { "input": "$$sa.someNestedArray", "as": "sn", "cond": { "$and": [ { "$eq": [ "$$sn.name", "value" ] }, { "$eq": [ "$$sn.otherField", 1 ] } ] } } } } }, }, "as": "sa", "cond": { "$and": [ { "$eq": [ "$$sa.name", "name1" ] }, { "$gt": [ { "$size": "$$sa.someNestedArray" }, 0 ] } ] } } } }} ]) 

Por lo tanto, en el conjunto “externo”, el $filter realmente ve el $size de la matriz “interna” después de que se “filtró” a sí mismo, por lo que puede rechazar esos resultados cuando toda la matriz interna coincida.

Mayores MongoDB

Para “proyectar” solo el elemento coincidente, necesita el método .aggregate() :

 db.mycollection.aggregate([ // Match possible documents { "$match": { "someArray.someNestedArray.name": "value" }}, // Unwind each array { "$unwind": "$someArray" }, { "$unwind": "$someArray.someNestedArray" }, // Filter just the matching elements { "$match": { "someArray.someNestedArray.name": "value" }}, // Group to inner array { "$group": { "_id": { "_id": "$_id", "name": "$someArray.name" }, "someKey": { "$first": "$someKey" }, "someNestedArray": { "$push": "$someArray.someNestedArray" } }}, // Group to outer array { "$group": { "_id": "$_id._id", "someKey": { "$first": "$someKey" }, "someArray": { "$push": { "name": "$_id.name", "someNestedArray": "$someNestedArray" }} }} ]) 

Eso le permite “filtrar” las coincidencias en matrices anidadas para uno o más resultados dentro del documento.