[SERVER-6074] Allow $slice operator in $project Created: 12/Jun/12  Updated: 06/Sep/17  Resolved: 14/Jul/15

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: 2.1.1
Fix Version/s: 3.1.6

Type: New Feature Priority: Major - P3
Reporter: Matt Weyant Assignee: Charlie Swanson
Resolution: Done Votes: 58
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by SERVER-13400 Allow $slice operator in aggregation ... Closed
is duplicated by SERVER-15083 Allow projection of specific array el... Closed
Related
related to CSHARP-1368 Allow $slice operator in $project Closed
related to SERVER-4589 aggregation: need an array indexing ... Closed
is related to DRIVERS-234 Aggregation Builder Support for 3.2 Closed
Backwards Compatibility: Minor Change
Sprint: Quint Iteration 4, Quint Iteration 5, Quint Iteration 6
Participants:

 Description   

Aggregation $project stage should support $slice operator on array fields similar to $slice in projection and syntax similar to aggregation $substr operator:

{ "$project" : { "newArray" : { "$slice" : [ "$oldarray" , 10, 4 ] } } }

The above would take 4 elements from oldarray starting at position 10 (akin to "skipping first ten elements, as position is 0 based).

Original description:

If I have a document with an array of values in it, I would like to be able to project a slice of those values while aggregating.

{ title: "A doc",
  intervals: [
    { value: 1, foo: true, bar: false },
    { value: 2, foo: false, bar: true },
    { value: 3, foo: true, bar: false}
  ]
}

$project with a $slice should work as expected:

{ $project : {
    title: 1,
    fewerIntervals: {intervals:{$slice:2}}
  }
}

results in a pipelined document =>

{ title: "A doc",
  fewerIntervals: [
    { value: 1, foo: true, bar: false },
    { value: 2, foo: false, bar: true }
  ]
}

Similarly, the remainder of the existing $slice syntax should work as expected.

{ $project : {
    title: 1,
    fewerIntervals: {intervals:{$slice:[1,1]}}
  }
}

should produce

{ title: "A doc",
  fewerIntervals: [
    { value: 2, foo: false, bar: true }
  ]
}



 Comments   
Comment by Charlie Swanson [ 14/Jul/15 ]

The new operator is called $slice. It takes either 2 or 3 arguments. In the two argument form, the first argument is the array to slice, and the second argument is the count of the number of elements to slice (positive or negative). Here are some examples of the two argument form:

> db.foo.drop()
> db.foo.insert({})
> db.foo.aggregate([{$project: {_id: 0, slice: {$slice: [[0,1,2,3], 2]}}}])
{ "slice" : [ 0, 1 ] }
> db.foo.aggregate([{$project: {_id: 0, slice: {$slice: [[0,1,2,3], -2]}}}])
{ "slice" : [ 2, 3 ] }

In the three argument form, the first argument is the array to slice, the second argument is the index from which to start the slice, and the third argument is the count of the number of elements to slice. Here are some examples of the three argument form:

> db.foo.aggregate([{$project: {_id: 0, slice: {$slice: [[0,1,2,3], 1, 2]}}}])
{ "slice" : [ 1, 2 ] }
> db.foo.aggregate([{$project: {_id: 0, slice: {$slice: [[0,1,2,3], -2, 1]}}}])
{ "slice" : [ 2 ] }
> db.foo.aggregate([{$project: {_id: 0, slice: {$slice: [[0,1,2,3], -2, 10]}}}])
{ "slice" : [ 2, 3 ] }

See the test in the commit for more details.

Comment by Githook User [ 14/Jul/15 ]

Author:

{u'username': u'cswanson310', u'name': u'Charlie Swanson', u'email': u'charlie.swanson@mongodb.com'}

Message: SERVER-6074 Add $slice aggregation expression
Branch: master
https://github.com/mongodb/mongo/commit/1e1bbec4cb0d9b8b418f9564dafba52d5e7417dd

Comment by Ramon Fernandez Marina [ 04/Jun/15 ]

All, as you can see in the "Fix Version/s" field this functionality has been scheduled for the upcoming development release 3.1.4, due in the coming weeks. At the time of this writing this feature is in code review, so we expect to be able to merge the code into master very soon.

Regards,
Ramón.

Comment by yogesh [ 04/Jun/15 ]

Any one found solution regarding this ?

Comment by Sam Verschueren [X] [ 16/Mar/15 ]

Is there a workaround for this issue? I have a lot of data and I only need the 10 first elements in the array when I aggregate.

Comment by Asya Kamsky [ 01/Feb/15 ]

newmanw we are aware of the desirability of this feature - we are definitely considering it (or possibly one of several similar requests that have some overlap - SERVER-4589 and SERVER-9377) for upcoming releases.

Comment by William Newman [ 31/Jan/15 ]

Gentle bump to ask if there are plans to implement this. Possible $limit on $push might help as well.

Comment by Roman [ 05/Nov/14 ]

Very strange that this Feature is not implemented yet!!

Comment by Antonio Quintana [ 15/Apr/14 ]

My use case:

I'm trying to get the top (and bottom) N cities, sorted by population and grouped by year.

After some $sorts's, $group's and $push's, I've got something like this:

{_id: "2013",
cities:["MEX", "CUN", "MIA", "JFK", "LHR", ...]
},
{ _id: "2014",
cities:["MEX", "MIA", "GCM", "JFK", "DFW", ...]]
}
.. and so on

Now, I want to do perform {$project: {cities: {$slice: N}}}

I think the $project operator should accept all of the operators the projection document does in the find() command

Comment by Pinte [ 10/Apr/14 ]

need it too

Comment by Sergey Smirnov [ 13/Feb/14 ]

It's really necessarry thing!

Comment by William Newman [ 11/Oct/13 ]

Any good work arounds for this issue? Really don't want to pull back millions of array values into memory to do the slice there. And map reduce is too slow.

Generated at Thu Feb 08 03:10:41 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.