Node.js: How to return an object in query aggregation?

I need to calculate the sum for a specified field from my collection using group by

So I used an aggregate function.

My wish is that the function should only return an object. When I use aggregate

it returns Array of Objects

.

But my query was returning an array of objects ( [{..}, {..}, {..}]

) not one object ( {..}

).

For example, So far I have tried

The structure is Array []

MyModel.aggregate(
  [
    {$match : ... },
    {$group : ... }
  ], function(err, result) {
      console.log(result);
}); 

      

Specified without structure [] structure

MyModel.aggregate(
    {$match : ... },
    {$group : ... }
  , function(err, result) {
      console.log(result);
});

      

The above both scripts return the same. as,

[
  {
    ...
    ...
  }
]

      

Expected result

onlyobject

{
  ...
  ...
}

      

+3


source to share


2 answers


Officially, the aggregate command takes a "list" of pipeline arguments as its primary input. This is why the "Array" syntax is preferred. While it is not strictly implemented this way with the mongoose method you are using, this could change.

"Official" arguments

  • Array representing the pipeline conditions

  • An options document defining various parameters for changing behavior.

So the mongoose shape just looks for which item in the "list" is function()

and counts everything in advance to be a pipeline. But that should change in the future. Your question though seems to have more to do with "expecting" a different form to create a "document" or "array" in response. But that won't happen.

You really are not and there is a good reason. The aggregation frame either manipulates the contents of the collection in the same way as and , or otherwise "groups" information such as . $project

$group



The only ways you usually expect only "one" to return is when you are either on purpose to get only one result, or the answer to one, or even if yours is in the singular or . $match

$limit

$group

null

This is usually assumed to be a "collection" of results, or presented here as an array. Modern MongoDB servers and driver implementations may actually return a "cursor", so the results may be greater than the 16MB BSON limit with newer versions. But still basically a list.

So this is always an array currently with something like "mongoose" that looks like you are using. Just return the "first element" when that's all you want. Maybe even the limit is 1:

MyModel.aggregate(
  [
    { "$match": ... },
    { "$group": ... },
    { "$limit": 1 }
  ], function(err, result) {
      console.log(result[0]);
});

      

Basically, all methods like .findOne()

are still done under the covers.

+6


source


I needed to do something similar to the above (ie use an aggregation pipeline - in my case, make a "join" using $ lookup - and similarly return only one (non-array) object). However, I also needed to return the promise for consistency. I then added after the .exec as follows to extract the object:



return myModel
.aggregate([
  { $match: {
    _id: ObjectId(args._id)} 
  },
  {
    $lookup: {
      from: "items",
      localField: "_id",
      foreignField: "itemId",
      as: "items"
    }
  }
])
.exec(function(err, pipelines) {
  if (err) {
    console.log('Error: ', err);
    return Promise.reject(new InternalError());
  }
})
.then(items => items[0]);

      

0


source







All Articles