Saltar al contenido

Cómo filtrar la matriz en un subdocumento con MongoDB

Solución:

Utilizando aggregate es el enfoque correcto, pero necesita $unwind los list matriz antes de aplicar el $match para que pueda filtrar elementos individuales y luego usar $group para volver a armarlo:

db.test.aggregate([
    { $match: {_id: ObjectId("512e28984815cbfcb21646a7")}},
    { $unwind: '$list'},
    { $match: {'list.a': {$gt: 3}}},
    { $group: {_id: '$_id', list: {$push: '$list.a'}}}
])

salidas:

{
  "result": [
    {
      "_id": ObjectId("512e28984815cbfcb21646a7"),
      "list": [
        4,
        5
      ]
    }
  ],
  "ok": 1
}

MongoDB 3.2 Actualización

A partir de la versión 3.2, puede utilizar la nueva $filter operador de agregación para hacer esto de manera más eficiente al incluir solo el list elementos que desea durante un $project:

db.test.aggregate([
    { $match: {_id: ObjectId("512e28984815cbfcb21646a7")}},
    { $project: {
        list: {$filter: {
            input: '$list',
            as: 'item',
            cond: {$gt: ['$$item.a', 3]}
        }}
    }}
])

La solución anterior funciona mejor si se requieren varios subdocumentos coincidentes. $ elemMatch también es muy útil si se requiere un único subdocumento coincidente como salida

db.test.find({list: {$elemMatch: {a: 1}}}, {'list.$': 1})

Resultado:

{
  "_id": ObjectId("..."),
  "list": [{a: 1}]
}

Usar agregación de $ filter

Selecciona un subconjunto de la matriz para devolver según la condición especificada. Devuelve una matriz con solo aquellos elementos que coinciden con la condición. Los elementos devueltos están en el orden original.

db.test.aggregate([
    {$match: {"list.a": {$gt:3}}}, // <-- match only the document which have a matching element
    {$project: {
        list: {$filter: {
            input: "$list",
            as: "list",
            cond: {$gt: ["$$list.a", 3]} //<-- filter sub-array based on condition
        }}
    }}
]);
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *