the0ffh
the0ffh

Reputation: 428

Aggregate - $push an Array Expression in $group

I have this aggregation pipeline:

{
    $project: {
        type: '$_id.type',
            datapoints: [
            {$multiply: ['$_id.timestamp', 1000]},
            '$count',
        ],
    },
},
{
    $group: {
        _id: {
            type: '$type',
        },
        datapoints: {$push: '$datapoints'},
    },
},

... which brought me to a following question:
How could I possibly append/push/add/etc an array to datapoints in $group (what could let me avoid $project stage))?

If I try putting the same expression for datapoints in the $project under $push in the $group it gives me an error

Upvotes: 2

Views: 3807

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151112

It's a fair point because you cannot just simply notate with "bracket" [] notation as available from MongoDB 3.2 into a $push.

It's a bit of a hack, but you can basically wrap the expression with $map instead of using the [] notation:

{ "$group": {
  "_id": "$_id.type",
  "datapoints": {
    "$push": {
      "$map": {
        "input": [1],
        "in": [
          { "$multiply": ["$_id.timestamp", 1000] },
          "$count"
        ]
      }
    }
  }
}}

Or even $concatArrays if your MongoDB supports it:

{ "$group": {
  "_id": "$_id.type",
  "datapoints": {
    "$push": {
      "$concatArrrays": [
        [
          { "$multiply": ["$_id.timestamp", 1000] },
          "$count"
        ]
      ]
    }
  }
}}

Or even $setUnion, which is actually probably the shortest to type, but it may not retain the order of elements if that is important to you:

{ "$group": {
  "_id": "$_id.type",
  "datapoints": {
    "$push": {
      "$setUnion": [
        [
          { "$multiply": ["$_id.timestamp", 1000] },
          "$count"
        ]
      ]
    }
  }
}}

Trying to simply do :

"datapoint": { "$push": [{ "$mulitply": [ ...

Will of course result in an error

"errmsg" : "The $push accumulator is a unary operator",

And this sort of expression would be syntactically incorrect:

"datapoint": { "$push": { ["a"] }

So you need an "expression" of some sort which is "unary" and not "list based" and returns a BSON Array in result. The above operators cover those cases.

Upvotes: 4

Related Questions