MongoDB: Cumulative values โ€‹โ€‹of all fields of a specific subdocument

I am trying to use MongoDB aggregate structure to create documents from a collection, which has the following structure:

{
  "_id" : ObjectId("5510eb56f877bbef153d236d"),
  "attributes" : {
    "brand" : "Mercedes",
    "price" : 289,
    "family" : "GARDEN"
  },
  "name" : "Bigger Fix Soft Crisps"
}
{
  "_id" : ObjectId("5510eb56f877bbef153d236e"),
  "attributes" : {
    "brand" : "Adelholzener",
    "price" : 683,
    "family" : "COMPUTER"
  },
  "name" : "Soft Stockhome Chips"
}
{
  "_id" : ObjectId("5510eb56f877bbef153d236f"),
  "attributes" : {
    "brand" : "Pepsi",
    "price" : 789,
    "family" : "CAR"
  },
  "name" : "Light Yearsailfresh Meat"
}

      

I want to get an aggregation of all fields from a subdirectory attributes

with their possible values. Since the fields in the sub-document are not known, I cannot just use the fields given in this example and therefore must be dynamic. The result should look something like this:

{
  "_id" : "brand",
  "values" : [
    "Mercedes", "Adelholzener", "Pepsi"
  ]
},
{
  "_id" : "price",
  "values" : [
    289, 683, 789
  ]
},
{
  "_id" : "family",
  "values" : [
    "GARDEN", "COMPUTER", "CAR"
  ]
}

      

I haven't found a solution for this specific problem yet. I've tried with $project

and $unwind

(which obviously only works for arrays).

+3


source to share


1 answer


Tried to figure out how to do this, aggregate, but I'm not sure if this is possible as you cannot get the keys in an object in any convenient way.

Here is MapReduce doing the following:



db.runCommand({
  "mapreduce" : "test_collection", // Change collection here
  "map" : function() {
    for (var key in this.attributes) {
      // Emit objects w array as we cannot reduce arrays directly
      emit(key, {x: [this.attributes[key]]});
    }
  },
  "reduce" : function(key, values) { 
    var res = [];
    values.forEach(function (d) {
      Array.prototype.push.apply(res, d.x);         
    });
    return {x: res};
  }, 
  "finalize": function (key, reducedVal) {
    return reducedVal.x;
  },
  "out": { inline: 1 }
});

      

+1


source







All Articles