[SERVER-14876] support $elemMatch in aggregation $project operator Created: 13/Aug/14 Updated: 25/Jun/15 Resolved: 20/May/15 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | Aggregation Framework |
| Affects Version/s: | 2.6.4 |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Major - P3 |
| Reporter: | Ben Rotz | Assignee: | Unassigned |
| Resolution: | Duplicate | Votes: | 6 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||
| Participants: | |||||||||
| Description |
|
Why can't $elemMatch be used in the $project phase? It would allow me to easily select an element out of an array. Example:
Basically what I'm looking for is an easier way to convert an array into a scalar without having to $unwind and then re-$group, which is taxing for proc time. |
| Comments |
| Comment by Charlie Swanson [ 22/May/15 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
Hi Laurent, Not yet, but it is very similar to the $map operator, except instead of $in to specify the transformation, it uses $cond to specify whether to include that element in the result array. Charlie | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Laurent Dollé [ 22/May/15 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
Hi Charlie, – Laurent | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Charlie Swanson [ 20/May/15 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
This use case is handled by the new $filter expression. | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Asya Kamsky [ 08/Apr/15 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
There is a workaround described for this in a related ticket: It involves using $project with $setDifference operator and avoids unwinding and re-grouping. | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleg Rekutin [ 07/Jan/15 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
I have a patch against 2.4 to implement this functionality as a new projection operator using the following syntax:
This will need rework to apply to 2.6+ (will actually be cleaner, I think), but meanwhile the 2.4 patch for this feature is: https://github.com/astral303/mongo/commit/b1de11d7af740676db4c9eeb85077ba6a4c2d103 For example, using Ben's originally reported data, here's a working aggregation and its result:
This syntax works with arrays of primitives too. You can see all the test cases here: I just wanted to get feedback on this syntax. I can then implement this against 2.6+. In my implementation, you cannot reference fields using the "$reference" syntax inside of the matcher expression itself. But I can solve very many problems without that ability, so I think it's still very worthwhile to have this. | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ben Rotz [ 03/Oct/14 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
For what it's worth, I tried to see if the $elemMatch operator was available using the "$let" command in the $project phase... and it is not. So no solution there, either. I'm running into an issue where even using the "current method" in the last code example above isn't working for my scenario, because the items inside the "people" array are being filtered out due to some match conditions after an unwind, but I would still like some of the information the array items that were filtered out... unfortunately not possible looks like, since I can't $project anything from an array into anything else. Please consider supporting $elemMatch in the project phase, it would have saved me tons of headache! Thanks! I have made a google posting about this here: https://groups.google.com/forum/#!topic/mongodb-user/4OrrFi98RmI | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ben Rotz [ 02/Oct/14 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
Just commenting to let you know there is still a need for me for this feature, I would really love it. A couple of clarifying points: 1) Right now, you can't use $elemMatch in the $project phase in the aggregation framework. Still a problem. 2) The $project phase for a find() does not have the ability to "rename" a field on its way out. That could be a useful addition as well, but I'm more concerned about the aggregation framework side of things. Assuming that $elemMatch could be used in the aggregation framework, It would be very useful if $elemMatch could be used underneath a field. For example, if I have a collection like
It would be nice to run
3) Right now, using $elemMatch in the find() command returns an array of the FIRST matched item. And it returns it in an array. This seems like a unhelpful combination. If $elemMatch will only EVER return one result, the result may as well be in scalar form. I see that there is already a ticket for matching MULTIPLE elements in the array at Using the example collection, a query to group by the name of the president and the number of records becomes trivial.
|