DeepSpace
DeepSpace

Reputation: 81654

Formatting the returned object from MongoDB/Mongoose group by

I have a MongoDB with documents of the form:

{
    ...
    "template" : "templates/Template1.html",
    ...
}

where template is either "templates/Template1.html", "templates/Template2.html" or "templates/Template3.html".

I'm using this query to group by template and count how many times each template is used:

var group = {
        key:{'template':1},
        reduce: function(curr, result){ result.count++ },
        initial: { count: 0 }
    };

    messageModel.collection.group(group.key, null, group.initial, group.reduce, null, true, cb);

I'm getting back the correct result, but it's formatted like this:

{
    "0" : {
        "template" : "templates/Template1.html",
        "count" : 2 },
    "1" : {
        "template" : "templates/Template2.html",
        "count" : 2 },
    "2" : {
        "template" : "templates/Template3.html",
         "count" : 1 }
}

I was wondering if it's possible to change the query so that it returns something like:

{
    "templates/Template1.html" : { "count" : 2 },
    "templates/Template2.html" : { "count" : 2 },
    "templates/Template3.html" : { "count" : 1 }
}

or even:

{
    "templates/Template1.html" : 2 ,
    "templates/Template2.html" : 2 ,
    "templates/Template3.html" : 1
}

I would rather change the query and not parse the returned object from the original query.

Upvotes: 0

Views: 1905

Answers (1)

Jason Cust
Jason Cust

Reputation: 10899

As mentioned by Blakes Seven in the comments you could use aggregate() instead of group() to achieve nearly your desired result.

messageModel.collection.aggregate([
  { // Group the collection by `template` and count the occurrences
    $group: {
      _id: "$template",
      count: { $sum: 1 }
    }
  },
  { // Format the output
    $project: {
      _id: 0,
      template: "$_id",
      count: 1
    }
  },
  { // Sort the formatted output
    $sort: { template: 1 }
  } 
]);

The output would look like this:

[
  {
    "template" : "templates/Template1.html",
    "count" : 2 },
  {
    "template" : "templates/Template2.html",
    "count" : 2 },
  {
    "template" : "templates/Template3.html",
    "count" : 1 }
  }
]

Again, as stated by Blakes in the comments the database can only output an array of objects rather than a solitary object. That would be a transformation that you would need to do outside of the database.

I think it deserves to be restated that this transformation produces an anti-pattern and should be avoided. An object key name provides the context or description for the value. Using a file location as a key name would be a fairly vague description whereas 'template' provides a bit more information about what that value represents.

Upvotes: 2

Related Questions