[SERVER-11536] $elemMatch matches too many elements Created: 03/Nov/13  Updated: 10/Dec/14  Resolved: 20/Jun/14

Status: Closed
Project: Core Server
Component/s: Write Ops
Affects Version/s: 2.2.2
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: NOVALUE Mitar Assignee: Ramon Fernandez Marina
Resolution: Done Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Mac OS X 10.7.5.


Issue Links:
Related
related to SERVER-11537 Incosistent behavior with $or and $el... Closed
Operating System: ALL
Steps To Reproduce:

If you do query:

 db.test.insert({nested: [{a: 1}, {a: 1}, {a: 2}]})
> db.test.find()
{ "_id" : ObjectId("52762cca359e2dd78d27d30e"), "nested" : [ { "a" : 1 }, { "a" : 1 }, { "a" : 2 } ] }
> db.test.update({'nested.a': 1, nested: {$elemMatch: {slug: {$ne: 'aaa'}}}}, {$set: {'nested.$.slug': 'aaa'}})
> db.test.find()
{ "_id" : ObjectId("52762cca359e2dd78d27d30e"), "nested" : [ { "a" : 1, "slug" : "aaa" }, { "a" : 1 }, { "a" : 2 } ] }
> db.test.update({'nested.a': 1, nested: {$elemMatch: {slug: {$ne: 'aaa'}}}}, {$set: {'nested.$.slug': 'aaa'}})
> db.test.find()
{ "_id" : ObjectId("52762cca359e2dd78d27d30e"), "nested" : [ { "a" : 1, "slug" : "aaa" }, { "a" : 1, "slug" : "aaa" }, { "a" : 2 } ] }
> db.test.update({'nested.a': 1, nested: {$elemMatch: {slug: {$ne: 'aaa'}}}}, {$set: {'nested.$.slug': 'aaa'}})
> db.test.find()
{ "_id" : ObjectId("52762cca359e2dd78d27d30e"), "nested" : [ { "a" : 1, "slug" : "aaa" }, { "a" : 1, "slug" : "aaa" }, { "a" : 2, "slug" : "aaa" } ] }

Array element with a == 2 should not be updated. At least this is not expected.

Participants:

 Description   

When using $elemMatch with normal field selectors they are not taken as union so more than expected array elements are matched.



 Comments   
Comment by NOVALUE Mitar [ 21/Jun/14 ]

OK, but shouldn't MongoDB combine this internally? The semantics of a comma is "and" operator?

Is this also the reason for #11537?

Comment by Ramon Fernandez Marina [ 20/Jun/14 ]

Hi mitar, apologies for the late reply. The right way to do what you want is to move the "nested.a" : 1 clause inside $elemMatch as follows:

db.test.update({nested: {$elemMatch: {a:1, slug: {$ne: 'aaa'}}}}, {$set: {'nested.$.slug': 'aaa'}})

After that change, the output of your script is what I think you're expecting:

{ "_id" : ObjectId("53a4a7c27661264ae90d13ec"), "nested" : [ { "a" : 1, "slug" : "aaa" }, { "a" : 1 }, { "a" : 2 } ] }
{ "_id" : ObjectId("53a4a7c27661264ae90d13ec"), "nested" : [ { "a" : 1, "slug" : "aaa" }, { "a" : 1, "slug" : "aaa" }, { "a" : 2 } ] }
{ "_id" : ObjectId("53a4a7c27661264ae90d13ec"), "nested" : [ { "a" : 1, "slug" : "aaa" }, { "a" : 1, "slug" : "aaa" }, { "a" : 2 } ] }

Hope this helps – thanks for using MongoDB!

Comment by NOVALUE Mitar [ 03/Nov/13 ]

Same on 2.4.8.

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