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?
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.
This means $first returns the first order type for the documents between the beginning of the partition and the current document.
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.
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.
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.
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"
}
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With