MervS
MervS

Reputation: 5902

Array subset in aggregation framework pipeline

In a previous question I wanted to obtain a count of the resulting groups using pipeline operations. As suggested, I used the following:

db.test.aggregate(
    {$unwind: '$tags'}, 
    {$group:{_id: '$tags', count:{$sum:1}}},
    {$project:{tmp:{tag:'$_id', count:'$count'}}}, 
    {$group:{_id:null, total:{$sum:1}, data:{$addToSet:'$tmp'}}}
)

Now having known the count, I would like to display the results by page so I would only need a subset of data. My initial thought would be using $slice on data within a $project pipeline like:

...
{$project: {data : { $slice: [20,20] }, total: 1}

But it appears that $slice is not a valid operation for $project. I tried a workaround by doing:

db.test.aggregate(
    {$unwind: '$tags'}, 
    {$group:{_id: '$tags', count:{$sum:1}}},
    {$project:{tmp:{tag:'$_id', count:'$count'}}}, 
    {$group:{_id:null, total:{$sum:1}, data:{$addToSet:'$tmp'}}},
    {$unwind: '$data'},
    {$skip: 20},
    {$limit: 20}
)

But as it appears, I performed another $unwind pipeline. Is there a better solution to achieve what I am trying to do?

Upvotes: 1

Views: 2782

Answers (2)

Salvador Dali
Salvador Dali

Reputation: 222601

As Stennie told, there is no $slice for an aggregation framework in 2.2 version of mongo, but in the upcomming 3.2 version of mongo they added it.

So now you can use $slice in aggregation. To return elements from either the start or end of the array: { $slice: [ <array>, <n> ] } To return elements from the specified position in the array: { $slice: [ <array>, <position>, <n> ] }.

And a couple of examples from the mongo page:

{ $slice: [ [ 1, 2, 3 ], 1, 1 ] }   // [ 2 ]
{ $slice: [ [ 1, 2, 3 ], -2 ] }     // [ 2, 3 ]
{ $slice: [ [ 1, 2, 3 ], 15, 2 ] }  // [  ]
{ $slice: [ [ 1, 2, 3 ], -15, 2 ] } // [ 1, 2 ]

Upvotes: 0

Stennie
Stennie

Reputation: 65333

Unfortunately there is currently (as at MongoDB 2.2) no Aggregation Framework operator to $slice or take a subset of an array.

You will need to use a workaround such as:

  • your use of $skip and $limit in the aggregate() pipeline
  • manipulation of the results in your application code.
  • implementing the aggregation using Map/Reduce

There is an existing feature request in the MongoDB issue tracker that you can upvote/watch: SERVER-6074: Allow $slice operator in $project.

Upvotes: 3

Related Questions