[SERVER-6050] Consider allowing $elemMatch applied to non arrays Created: 09/Jun/12  Updated: 14/May/20  Resolved: 16/Jun/16

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

Type: Improvement Priority: Major - P3
Reporter: Aaron Staple Assignee: David Storch
Resolution: Duplicate Votes: 16
Labels: query_triage
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Depends
Duplicate
duplicates SERVER-15086 Allow for efficient range queries ove... Closed
is duplicated by SERVER-5320 Make $elemMatch support single object Closed
Related
related to SERVER-7959 Potentially unexpected scans with com... Closed
related to SERVER-47925 Add a new $elemMatch-like operator wh... Backlog
is related to SERVER-1264 $elemMatch on subArray Closed
Participants:

 Description   

Currently $elemMatch can only be applied to an array. For example { a:{ $elemMatch:{ $gte:1, $lte:10 } } } will match { a:[ 5 ] } but not { a:5 }. This is a bit awkward in a case like { 'a.b':{ $elemMatch:{ $gte:1, $lte:10 } } } and a document { a:[ { b:5 }, { b:15 } ] }. The document will not match because the b values are not arrays, even though there could be multiple values of 'a.b'.



 Comments   
Comment by David Storch [ 16/Jun/16 ]

Hi all,

The need for this change in behavior of the $elemMatch operator has been eliminated by work done under SERVER-15086. Therefore, I am closing this request as a duplicate. Starting in 3.4, the server will track which field paths in an index are multikey, and use this information to generate more efficient query plans. Please see the description of SERVER-15086 for more detailed information on the new behavior offered in 3.4, including an example demonstrating the kinds of queries which will benefit.

Best,
Dave

Comment by Nate Smith [ 24/Jun/15 ]

Please do address this. Being able to efficiently query a field within an object in an array is something very valuable for our reporting implementation, and the current workarounds require storing data in a very unintuitive and awkward format.

Comment by Oleg Rekutin [ 11/Jun/15 ]

I agree that the first desire/usecase described is backwards breaking and not desirable, given that Eduardo replied to the original reporter with a query that works today. Many queries in Mongo are tricky to put together (e.g. it required Eduardo's experience to realize that he needs to build the kind of query that he supplied), but unfortunately that's the world of Mongo querying. In my experience, while I would it find it likely having to write queries like these, I find it a lot less likely to write code that stores either a single value as or an array of values under the same key name (and that's usually something that is easily addressed in the code doing the writing).

Comment by Asya Kamsky [ 11/Jun/15 ]

If this ticket was implemented, it must be considered backwards breaking, since currently it's possible to use $elemMatch to test for a match that is only satisfied by an array element, i.e. changing this behavior would change results of queries on collections which have fields that have both array and non-array values that match.

Comment by Ben Rotz [ 25/Sep/14 ]

It seems that this suggestion would provide a fix for SERVER-15086. Please upvote this ticket and also SERVER-15086 as it would provide a much needed fix for using indexes on range queries of scalar values inside of arrays.

Thanks!

Comment by Eduardo Manso [ 22/Feb/13 ]

I don't think that applying $elemMatch to non arrays would be a good idea, but, I agree with you about the issue on searching objects inside arrays.

The following query works perfect for your example:

INDEX -

{"a.b":1}

QUERY - {"a":{ $elemMatch:{ "b":{$gte:1, $lte:10} } } }

In this case $elemMatch is related to "a", what is the correct way to do that, and the condition {$gte:1, $lte:10} is related to "b".

In my point of view, there is no need for changing $elemMatch behavior. But there is a problem here that I've tried to explain on SERVER-8610. If you use the above query, it will work as expected but it will not use de index

{"a.b":1}

as it should. What happens is that It uses the index but just the "$gte" part, so it starts at "$gte:1" and don't stops at "$lte:10"... it just scans the whole index, without respecting the RANGE "1~10".

Please, see SERVER-8610 and, if you agree, help me voting for this urgent fix.

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