[SERVER-6612] Support projecting multiple array values in a projection like the $elemMatch projection specifier Created: 26/Jul/12  Updated: 06/Dec/22  Resolved: 17/Jan/18

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: 2.2.0-rc0
Fix Version/s: None

Type: New Feature Priority: Major - P3
Reporter: Ben Becker Assignee: Backlog - Query Team (Inactive)
Resolution: Duplicate Votes: 37
Labels: projection
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Duplicate
duplicates SERVER-17943 add $filter expression to $project to... Closed
is duplicated by SERVER-7224 Add $filter operator to filter subdoc... Closed
is duplicated by SERVER-9028 Using positional operator with db.col... Closed
Related
is related to SERVER-2238 New projection operator $elemMatch Closed
Assigned Teams:
Query
Backwards Compatibility: Fully Compatible
Participants:

 Description   

The idea is to support a projection specifier like $elemMatch, but which can return multiple results from a single array. Something like $elemMatchAll or $elemMatchAny might make sense, but the projection syntax will need to be thoroughly vetted.



 Comments   
Comment by Asya Kamsky [ 08/Nov/15 ]

As of 3.2 this is possible in the aggregation framework directly via the $filter expression in $project. See SERVER-17943 for more details.

Comment by Miroslav Nedyalkov [ 17/Jun/15 ]

This works perfect, but doesn't it hurt the performance? It projects the collection and makes set difference just to filter it out.

Comment by Jon Rangel (Inactive) [ 16/Jan/15 ]

As a workaround, I found it's possible to get the same projection behaviour using the aggregation framework:

 
// match criteria for each array element - CHANGE THIS AS REQUIRED
var elem_match = { "$eq" : [ "$$array_elem.key", 1 ] };
 
// replace each non-matching array element with null
var map = {
    "$map" : {
        "input" : "$array",
        "as" : "array_elem",
        "in" : { "$cond" : [ elem_match, "$$array_elem", null ] }
    }
};
 
// filter out the null array elements
var set_diff = { "$setDifference" : [ map, [ null ] ] };
 
var project = { "$project" : { "array" : set_diff } };
 
db.foo.aggregate([project]);

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