[SERVER-55005] $elemMatch not matching all elements Created: 05/Mar/21  Updated: 21/May/21  Resolved: 21/May/21

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: 4.4.4
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Nikita Mikhaylov Assignee: Eric Sedor
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Steps To Reproduce:

> db.table.insert({_id: 1, foo: [{"bar": {a: 1, b : 2}}]})
WriteResult({ "nInserted" : 1 })
> db.table.findOne({foo: {$elemMatch: {"bar" : {a:1, b:2}}}})
{
        "_id" : 1,
        "foo" : [
                {
                        "bar" : {
                                "a" : 1,
                                "b" : 2
                        }
                }
        ]
}
> db.table.findOne({foo: {$elemMatch: {"bar" : {b:2, a:1}}}})
null

Participants:

 Description   

$elemmatch operator seems to be faulty when matching complex objects, the order of keys inside the object determines whether the object matches the query.

Tested the behaviour on 3.6.8 and 4.4.4



 Comments   
Comment by Eric Sedor [ 08/Mar/21 ]

This documentation describes the behavior you are seeing.

For further discussion about how to make this work for your data, I'd like to ask you to post on the MongoDB Developer Community Forums. The community there can provide good guidance there on how to use elemMatch and also index for its use.

If the discussion there leads you to suspect a bug in the MongoDB server, or to identify a specific improvement to request, then we'd want to discuss here in the SERVER project, which is for bugs and feature suggestions for the MongoDB server.

Gratefully,
Eric

Comment by Nikita Mikhaylov [ 08/Mar/21 ]

Hi Eric,

This looks correct for the syntax of querying whether or not "bar" is a subdocument. Order is considered when querying like this.

I don't think I quite understand what you mean by 'This looks correct for the syntax of querying whether or not "bar" is a subdocument.'
Is there any documentation/example that you can provide with a similar oddity? Is it a thing that is not specific to $elemMatch? Are all subdocument queries affected this way?

You should be able to query for nested fields independent of their order using this syntax: 

db.table.findOne({"foo": {$elemMatch:{"bar.b":2,"bar.a":1}}})

Although technically correct, unfortunately in my case, this will not be good enough, the collection is very big and without an index, it is not going to work.
As far as I can see from query.explain, MongoDB will not be able to use the index https://gist.github.com/Noobgam/d46c583e0b173c4f8222bac32bab7b86

Comment by Eric Sedor [ 08/Mar/21 ]

Hi shessmaster12@gmail.com,

This looks correct for the syntax of querying whether or not "bar" is a subdocument. Order is considered when querying like this. You should be able to query for nested fields independent of their order using this syntax: db.table.findOne({"foo": {$elemMatch: {"bar.b":2,"bar.a":1})}}.

Does this sound right?

Eric

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