humano
humano

Reputation: 99

Show only an element found in an array in mongodb

I have this collection:

/* 1 */
{
    "_id" : ObjectId("553e316e39108e802a1edeb9"),
    "coleccion" : "aplicaciones",
    "nombre" : "otra aplicacionn",
    "descripcion" : "w aplicacion",
    "tipo" : "privada",
    "campoId" : [ 
        {
            "id" : "1430230303",
            "id_campo" : "553bffed39108e346ccff7ab",
            "orden" : "25",
            "obligatorio" : "0"
        }, 
        {
            "id" : "1430233750",
            "id_campo" : "553bffca39108eb163cff7aa"
        }, 
        {
            "id" : "1430233753",
            "id_campo" : "553c001139108ebc63cff7aa",
            "orden" : "47",
            "estado" : "1"
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("553ce99a39108e2b7c1edeb9"),
    "coleccion" : "aplicaciones",
    "nombre" : "Mascotas",
    "descripcion" : "Censo de mascotas",
    "tipo" : "publica",
    "campoId" : [ 
        {
            "id" : "1430230465",
            "id_campo" : "553bffed39108e346ccff7ab",
            "orden" : "19",
            "obligatorio" : "0"
        }, 
        {
            "id" : "1430231597",
            "id_campo" : "553bffca39108eb163cff7aa",
            "estado" : "1",
            "obligatorio" : "1"
        }, 
        {
            "id" : "1430419469",
            "id_campo" : "554277d839108e6a5835c3e0",
            "orden" : "39",
            "obligatorio" : "0"
        }, 
        {
            "id" : "1430423643",
            "id_campo" : "553c001139108ebc63cff7aa",
            "orden" : "64",
            "obligatorio" : "1"
        }
    ]
}

And I want to find a specific element within the array like this:

"obligatorio" : "1"

Searching for the field :

"id" : "1430231597"

I've tried:

db.getCollection('aplicaciones').find({campoId:{$elemMatch:{"id":"1430231597"}}},{"campoId.$.obligatorio":1,_id:0})

but I get

{
"campoId" : [ 
    {
        "id" : "1430231597",
        "id_campo" : "553bffca39108eb163cff7aa",
        "estado" : "1",
        "obligatorio" : "1"
    }
]

}

How to make so that the result is just the value of the " obligatiorio" field ?

Upvotes: 2

Views: 77

Answers (1)

Sede
Sede

Reputation: 61225

You can do this using "aggregation".

db.aplicaciones.aggregate(
    [   
        { "$match": { "campoId.id": "1430231597" }},
        { "$unwind": "$campoId" }, 
        { "$match": { "campoId.id":"1430231597" }}, 
        { "$project": { "obligatorio": "$campoId.obligatorio", "_id":0 }}
    ]
)

But the best way is using the $setDifference and the $map operators because $unwind can be "expensive"

db.aplicaciones.aggregate([ 
    { "$match": { "campoId.obligatorio": "1" }}, 
    { "$project": { "campoId": { 
        "$setDifference": [ 
            { "$map": { 
                "input": "$campoId",
                "as": "cp", 
                "in": { 
                    "$cond": [{ 
                        "$and": [ 
                            { "$eq": ["$$cp.obligatorio", "1" ]},
                            { "$eq": [ "$$cp.id", "1430231597" ]}  
                        ]}, 
                        "$$cp", 
                        false
                    ]
                }}
            }, 
            [false]
       ]}
    }}
])

which yields:

{
        "_id" : ObjectId("553ce99a39108e2b7c1edeb9"),
        "campoId" : [
                {
                        "id" : "1430231597",
                        "id_campo" : "553bffca39108eb163cff7aa",
                        "estado" : "1",
                        "obligatorio" : "1"
                }
        ]
}

Upvotes: 2

Related Questions