Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting mongo array to object with key-value pair

I have a mongo document that contains an array of Strings, and I need to convert this particular array of strings into an array of object containing a key-value pair. Below is my curent appraoch to it.

{
    "_id" : ObjectId("57e3720836e36f63695a2ef2"),
    "platform" : "A1",
    "available" : {
        "Community" : {
            "attributes" : {
                "type" : {
                    "values" : [
                        "well-known",
                        "simple",
                        "complex"
                    ],
                    "defaultValue" : "well-known"
                },
[......]


}

Current Query:

templateAttributes.find({platform:"V1"}).map(function(c){
  //instantiate a new array
  var optionsArray = [];
for (var i=0;i< c['available']['Community']['attributes']['type']['values'].length; i++){
    optionsArray[i] = {};              // creates a new object
    optionsArray[i].label = c['available']['Community']['attributes']['type']['values'][i];
    optionsArray[i].value = c['available']['Community']['attributes']['type']['values'][i];
    }
    return optionsArray;
})[0];

Result:

[{label:"well-known", value:"well-known"},
{label:"simple", value:"simple"},
{label:"complex", value:"complex"}]

Is my approach efficient enough, or is there a way to optimize the above query to get the same desired result?

like image 343
blueren Avatar asked Sep 23 '16 06:09

blueren


People also ask

What is $$ in MongoDB?

The $map has parameters - input which specifies the array field name, as specifies the current array element identifier in an iteration, and in where each array element is processed in the iteration. Within the in , the current array element is referred using the $$ prefix - this is the syntax required.

What is $first in MongoDB?

This means $first returns the first order type for the documents between the beginning of the partition and the current document.

How do I use arrayToObject in MongoDB?

In MongoDB, the $arrayToObject aggregation pipeline operator converts an array to a document. The array provided to $arrayToObject must be in one of the two following formats: An array of two-element arrays where the first element is the field name, and the second element is the field value.

How do I pull an element from an array in MongoDB?

To remove an element, update, and use $pull in MongoDB. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.


Video Answer


2 Answers

Not so sure what you want to do with the end result as the keys and the values are just the same. Nonetheless, you can use the aggregation framework where you can denormalise the embedded values array by using the $unwind operator which flattens it i.e. it produces a copy of each document per array entry.

After flattening the values array, you can apply the $group accumulation operators on the values to aggregate them. A final pipeline of the $project operator would shape the fields from the previous grouping into the desired format.

Follow this example to get the concept:

templateAttributes.aggregate([
    { "$match": { "platform": "V1" } },
    { "$unwind": "$available.Community.attributes.type.values" },
    {
        "$group": {
            "_id": "$available.Community.attributes.type.values",
            "value": { "$first": "$available.Community.attributes.type.values" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "label": "$_id",
            "value": 1
        }
    }
])

Since you are using Meteor, meteor add meteorhacks:aggregate will add proper aggregation support for Meteor so that you can run the above aggregation pipeline on your collection.

like image 140
chridam Avatar answered Sep 17 '22 14:09

chridam


Please use aggregation here.

db.templateAttributes.aggregate([
                                    {"$match":{platform:"A1"}}, {"$unwind": "$available.Community.attributes.type.values"}, 
                                    {$group: {"_id": null, "val":{"$push":{label:"$available.Community.attributes.type.values", 
                                                                            value:"$available.Community.attributes.type.values"}}}}
                                ]).toArray()[0].val

Output:

[
    {
            "label" : "well-known",
            "value" : "well-known"
    },
    {
            "label" : "simple",
            "value" : "simple"
    },
    {
            "label" : "complex",
            "value" : "complex"
    }
]
like image 41
4J41 Avatar answered Sep 19 '22 14:09

4J41