[SERVER-16284] Allow for $pushall / $push with $each to allow pushing all elements of array in $group Created: 22/Nov/14 Updated: 31/Oct/23 |
|
| Status: | Open |
| Project: | Core Server |
| Component/s: | Aggregation Framework |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | New Feature | Priority: | Major - P3 |
| Reporter: | John Butler | Assignee: | Backlog - Query Optimization |
| Resolution: | Unresolved | Votes: | 20 |
| Labels: | accumulator, aggregate, asya, expression, needs-scope-approval, needs-syntax, pm1457-nominee | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||||||||||||||
| Assigned Teams: |
Query Optimization
|
||||||||||||||||||||||||||||
| Participants: | |||||||||||||||||||||||||||||
| Description |
|
I would like to be able to push all elements of an array field into a new field. So, in a $group, I could do a $push or $addToSet of a field that is an array field and the resulting field would be an array of the elements instead of an array of arrays. Seems like the $each operator in update is the solution if added to aggregations. |
| Comments |
| Comment by Asya Kamsky [ 11/Aug/21 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Ran into this again here: https://www.mongodb.com/community/forums/t/group-multi-dimensional-array-after-unwinding-elements/117554/3 where the solution required flattening arrays of arrays because there was no way to $pushAll.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 26/Jul/17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
SERVER-29339 would allow this, and any other arbitrary grouping but I would agree that the more common use cases should have simplest possible syntax. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marc Tinkler [ 26/Jul/17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Just my 2 cents, but if you are going to be adding accumulators like $mergeObjects ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by David Storch [ 23/Jan/17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
As noted in
there should be an easy way to reduce this to either {_id: "myGroup", resultArr: [1, 2, 3, 4]} or {_id: "myGroup", resultArr: [1, 2, 3, 2, 3, 4]}. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Neil Lunn [ 24/Apr/16 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I would actually see this more in this form:
Where accumulators functioned something like the following and without needing to resort to $unwind
Or even as an allowed "modifier" from a syntax point of view
Point being that there should be an operator syntax for applying each element of an existing array or "set" without needing to resort to $unwind. The $unwind operation should be reserved for cases where it is necessary to actually transfer elements from those arrays into part of the grouping key itself. Allowing such modifiers and even $sort as well removes various use cases requiring $unwind and should significantly improve performance where the array/"set" can be merged/sorted within the accumulator result. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Charlie Swanson [ 05/Nov/15 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I should add to my example that $slice is new in 3.2, so this won't work against a mongod <=3.0, but the point remains, any expression can be used in the group stage, just substitute $slice for your favorite projection operator. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Charlie Swanson [ 04/Nov/15 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
That ticket is slightly misnamed. You can use the $slice operator in a $group stage, just as you can use any other operator available in the project stage. e.g. given the following documents:
You can run the following pipeline
To get this result
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oliver Eberle [ 28/Jul/15 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
It would be nice if $push in aggregation could support $each and @slice etc. Having the option to limit array items with slice in the $project stage is now supported ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by John Butler [ 26/Nov/14 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
So yes, I am familiar with unwind but here is how it ended up. In my case I would like to do a two-step group. Group 1 produces a count and creates new arrays of values. Group 2 gives me an overall count and concatenates the two arrays (via the $pushall or $push / $each to produce an array of values instead of an array or arrays). Instead of doing the aggregation as two simple groups, I have to do the following: group1 So yes, I was able to do a workaround. The point however is that this seems to be a functionality ($each I believe) that would not be uncommonly used if available in aggregate and seems to be available for update. I ask that you make it available in aggregate as well. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ramon Fernandez Marina [ 25/Nov/14 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
You may want to try using the $unwind operator to achieve what you need; for example:
Is this the behavior you're looking for? |