Santiago Esquivel
Santiago Esquivel

Reputation: 380

Finding nested array mongodb

So I have a mongodb document looking like this:

[
    {
        "_id": "04",
        "name": "test service 4",
        "id": "04",
        "version": "0.0.1",
        "title": "testing",
        "description": "test",
        "protocol": "test",
        "operations": [
            {
                "_id": "99",
                "oName": "test op 52222222222",
                "sid": "04",
                "name": "test op 52222222222",
                "oid": "99",
                "description": "testing",
                "returntype": "test",
                "parameters": [
                    {
                        "oName": "Param1",
                        "name": "Param1",
                        "pid": "011",
                        "type": "582",
                        "description": "testing",
                        "value": ""
                    },
                    {
                        "oName": "Param2",
                        "name": "Param2",
                        "pid": "012",
                        "type": "58222",
                        "description": "testing",
                        "value": ""
                    }
                ]
            }
        ]
    }
]

I want to be able to find all of the parameters and an individual one but I am not entirely sure how, if I use this:

 collection.find({operations: {$elemMatch: {oid: oid}}}, {"operations.$.parameters": 1}).toArray(function(error, result) {
    if (error) {
        console.log('Error retrieving parameter: ' + error);
        res.send({'error':'An error has occurred'});
    } else {
        // console.log(result);
        res.send(result);
    }
});

the output I get is this:

[
    {
        "_id": "04",
        "operations": [
            {
                "_id": "99",
                "oName": "test op 52222222222",
                "sid": "04",
                "name": "test op 52222222222",
                "oid": "99",
                "description": "testing",
                "returntype": "test",
                "parameters": [
                    {
                        "oName": "Param1",
                        "name": "Param1",
                        "pid": "011",
                        "type": "582",
                        "description": "testing",
                        "value": ""
                    }
                ]
            }
        ]
    }
]

even though the only thing I want is the individual parameter. Is there are any way I can get this done?

Upvotes: 1

Views: 49

Answers (1)

chridam
chridam

Reputation: 103365

You could use the aggregation framework for this:

var oid = "99",
    pipeline = [
    {
        $match: {
            "operations.oid": oid
        }
    },
    {
        $unwind: "$operations"
    },
    {
        $match: {
            "operations.oid": oid
        }
    },
    {
        $unwind: "$operations.parameters"
    },
    {
        $project: {            
            "parameters": "$operations.parameters"
        }
    }
];

collection.aggregate(pipeline).toArray(function(error, result) {
    if (error) {
        console.log('Error retrieving parameter: ' + error);
        res.send({'error':'An error has occurred'});
    } else {
        // console.log(result);
        res.send(result);
    }
});

Output:

    [ 
        {
            "_id" : "04",
            "parameters" : {
                "oName" : "Param1",
                "name" : "Param1",
                "pid" : "011",
                "type" : "582",
                "description" : "testing",
                "value" : ""
            }
        }, 
        {
            "_id" : "04",
            "parameters" : {
                "oName" : "Param2",
                "name" : "Param2",
                "pid" : "012",
                "type" : "58222",
                "description" : "testing",
                "value" : ""
            }
        }
    ]

EDIT:

To access an individual parameter given a pid value, you can modify the pipeline by adding a $match pipeline stage between the $unwind and $project stages so that you can filter the documents to return the parameter object matching pid :

var oid = "99", 
    pid = "011",
    pipeline = [
        {
            $match: {
                "operations.oid": oid
            }
        },
        {
            $unwind: "$operations"
        },
        {
            $match: {
                "operations.oid": oid
            }
        },
        {
            $unwind: "$operations.parameters"
        },
        // This pipeline stage returns the individual parameters object that matches the given pid value
        {
            $match: { "operations.parameters.pid": pid }
        },
        {
            $project: {            
                "parameters": "$operations.parameters"
            }
        }
    ];

Output:

[ 
    {
        "_id" : "04",
        "parameters" : {
            "oName" : "Param1",
            "name" : "Param1",
            "pid" : "011",
            "type" : "582",
            "description" : "testing",
            "value" : ""
        }
    }
]

Upvotes: 1

Related Questions