[SERVER-2238] New projection operator $elemMatch Created: 16/Dec/10  Updated: 05/Mar/13  Resolved: 15/Jun/12

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: None
Fix Version/s: 2.1.2

Type: New Feature Priority: Minor - P4
Reporter: Hannes Assignee: Ben Becker
Resolution: Done Votes: 19
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Related
related to SERVER-6613 using $elemMatch projection with $all... Closed
related to SERVER-6612 Support projecting multiple array val... Closed
related to CSHARP-683 Add new features to Query builder for... Closed
is related to SERVER-828 Support for selecting array elements ... Closed
is related to DOCS-422 Add doc for $elemMatch operator Closed
Participants:

 Description   

Instead of a $ positional operator in projections ( as proposed here: http://jira.mongodb.org/browse/SERVER-828 ), I think that we could use a $elemMatch operator in projections, which will be used similiar to $slice.
An example in pseudo-js:
doc = {'a' : [

{'b':1}

,

{'b':2}

,

{'b':3}

],'c' :4}

project( {'a' : [

{'b':1}

,

{'b':2}

,

{'b':3}

] }, {'a':{$elemMatch:

{'b':2}

}} )
will be evaluated to:
{'a' : [

{'b':2}

],'c' :4}

project( {'a' : [

{'b':1}

,

{'b':2}

,

{'b':3}

] }, {'a':{$elemMatch:{'b':{'$gte':2}}}} )
will be evaluated to:
{'a' : [

{'b':2}

,

{'b':3}

],'c' :4}

The advantage over the $-operator is that, the projection is completly independent from the matching. So you could match on something completly different and return only the entries you want. Furthermore this should be easier to implement.

The only problem I see is that, you will in many cases repeat yourself, because you want to extract the fields you are querying for.



 Comments   
Comment by auto [ 03/Sep/12 ]

Author:

{u'date': u'2012-09-02T23:51:06-07:00', u'email': u'stennie@10gen.com', u'name': u'Stephen Steneker'}

Message: DOCS-338: Clarification that elemMatch projection only returns first match found (per SERVER-2238)
Branch: master
https://github.com/mongodb/docs/commit/234b3a99cc8a0222c27c5d040265588ea5d8e344

Comment by auto [ 30/Jul/12 ]

Author:

{u'date': u'2012-07-27T20:11:08-07:00', u'email': u'jeff.yemin@10gen.com', u'name': u'Jeff Yemin'}

Message: More tests for SERVER-828 and SERVER-2238
Branch: master
https://github.com/mongodb/mongo/commit/83ec59844bdd629b2b32a9791a4e7a0e93516c02

Comment by Ben Becker [ 26/Jul/12 ]

Just wanted to update some of the implementation details of this feature:

  1. The $elemMatch projection specifier will only match one element
  2. The projection should match the same element as the '$' positional operator (see SERVER-828).
  3. $elemMatch does not provide a way to sort the projected array (this could be very expensive).
  4. sort() still applies to the documents in the result set and does not impact the array element returned.

This ticket outlines a nice feature to have, which is to match multiple elements in an array. This was not implemented in the first pass due to interface and performance implications. It's unlikely the behavior of $elemMatch will change (to ensure we don't break compatibility), but I have filed SERVER-6612 to address that case in a future version.

Comment by Ben Becker [ 15/Jun/12 ]

This was implemented along with SERVER-828:

https://github.com/mongodb/mongo/commit/fb66c84bc7bc1ece63a65766bfea2f797f3b7121

Comment by Azat Khuzhin [ 27/Mar/12 ]

How with this feature will work sort()

For example, if I add index on "doc.a.b" (see head of issue)
Is mongodb can sort(

{"doc.a.b": -1}

) documents using my index and is it will be sort using only that fields that I set using $elemMatch?

Comment by Hannes [ 10/Jan/11 ]

Hi Bradford.

Nice idea. I thought about this feature for Arrays. But it might be surely helpful, if it was implemented for Hashes, too. Let's see what the Mongo-Developer think about it!

Comment by Bradford Smith [ 05/Jan/11 ]

I really can't wait for this feature. Mine is a little different, where I don't know the element to match on, because it's a randomly generated ID. Would this case be handled? I want all matched documents, but only include notes where hide == true.

// given
{
"_id" : "store1",
"name": "Store 1",
"notes" : {
"4d221860edc6ae20218cc50a" :

{ "text" : "aaa", "hide" : false }

,
"4d221860edc6ae20218cc50b" :

{ "text" : "bbb", "hide" : true }

,
"4d221860edc6ae20218cc50c" :

{ "text" : "ccc", "hide" : true }

}

}

// yield
{
"_id" : "store1",
"name": "Store 1",
"notes" : {
"4d221860edc6ae20218cc50b" :

{ "text" : "bbb", "hide" : true }

,
"4d221860edc6ae20218cc50c" :

{ "text" : "ccc", "hide" : true }

}
}

// additionally, it'd be nice to sort on notes.text desc:
{
"_id" : "store1",
"name": "Store 1",
"notes" : {
"4d221860edc6ae20218cc50c" :

{ "text" : "ccc", "hide" : true }

,
"4d221860edc6ae20218cc50b" :

{ "text" : "bbb", "hide" : true }

}
}

I agree that this feature would make embedded documents more practical.

Comment by Olivier Allouch [ 26/Dec/10 ]

Sounds great, and if it can use indexes, it's gonna change the way we design our databases, as we won't be afraid to store a huge amount of embedded documents.

Generated at Thu Feb 08 02:59:22 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.