1

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?

1 Answer 1

1

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" : ""
        }
    }
]
Sign up to request clarification or add additional context in comments.

7 Comments

This is exactly what I needed, thank you. How would you modify this if you just want an individual parameter? I have access to the pid through req.params.parameters
@SantiagoEsquivel No worries :-) I have modified my answer to address that part.
Thats amazing, I cannot thank you enough, I have been struggling with this last bit in my program a lot the last couple days.
@SantiagoEsquivel That's ok. Bear in mind that the $match, $sort, $limit, and $skip pipeline operators can take advantage of an index when they occur at the beginning of the pipeline before any of the following aggregation operators: $project, $unwind, and $group. So if you have indexes on the fields used in the $match operators above your aggregation query could perform a bit faster.
Just as a last followup, if I wanted to do an update on any of the given parameters, how should I go about to do this? I tried using $elemMatch but the changes are not reflected, I can make another question in order to explain myself further if needed
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.