[SERVER-30998] Update and $ operator mismatch with multiple arrays in query Created: 08/Sep/17  Updated: 08/Sep/17  Resolved: 08/Sep/17

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: 3.4.1, 3.4.7, 3.5.12
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Henri-Maxime Ducoulombier Assignee: David Storch
Resolution: Duplicate Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates SERVER-18500 Resolve ambiguity of positional proje... Backlog
Related
is related to SERVER-27089 Extend the update subsystem to suppor... Closed
Operating System: ALL
Participants:

 Description   

Consider a simple collection with a single document, build this way :

("a" and "a2" fields are used to demonstrate the update behavior below)

db.mongo.insert(
{
	"a":[NumberInt(123), NumberInt(456), NumberInt(789)],
	"a2": NumberInt(456),
	"b":{
		"c":[
			{"d":NumberInt(10), "e":NumberInt(20)},
			{"d":NumberInt(10), "e":NumberInt(21)},
			{"d":NumberInt(10), "e":NumberInt(22)},
			{"d":NumberInt(10), "e":NumberInt(23)},
			{"d":NumberInt(10), "e":NumberInt(24)},
			{"d":NumberInt(11), "e":NumberInt(25)},
			{"d":NumberInt(11), "e":NumberInt(26)},
			{"d":NumberInt(11), "e":NumberInt(27)},
		] 
	} 
}
);

My goal is to update array b.c and add elements to a set where d = 10 and e = 24, only for document where a = 456.

This first query does not work : it updates the element in array b.c with the position of "456" in the a array ( = the second element), even with the $elemMatch on b.c.

db.mongo.update(
	{
	 	"a": NumberInt(456),
	 	"b.c": {
	 	  "$elemMatch": {
	 	    "d": NumberInt(10),
	 	    "e": NumberInt(24)
	 	    }
	 	  }
	},
	{
		"$addToSet":{
			"b.c.$.f":{"x":NumberInt(1), "y":NumberInt(2)}
		}
	}
);

This second query does work : it updates the correct element in array because a2 is not an array. This issue being, I need a to be an array and hold several values.

db.mongo.update(
	{
	 	"a2": NumberInt(456),
	 	"b.c": {
	 	  "$elemMatch": {
	 	    "d": NumberInt(10),
	 	    "e": NumberInt(24)
	 	    }
	 	  }
	},
	{
		"$addToSet":{
			"b.c.$.f":{"x":NumberInt(1), "y":NumberInt(2)}
		}
	}
);

I have tried to change the order of the conditions in the query part, but this does not change the behavior.

Any help (or even better, a fix..) would be greatly appreciated.

Tested on 3.4.1, 3.4.7 and 3.5.12 (to see if the changes in SERVER-831 would fix it.



 Comments   
Comment by David Storch [ 08/Sep/17 ]

Hi hmducoulombier@marketing1by1.com,

This looks like a duplicate of SERVER-18500. When there are multiple query predicates which must implicitly traverse arrays (in your case, the match on field a and the $elemMatch on b.c), then the semantics of the positional update operator ($) are ambiguous.

Please note that in development release 3.5.12, we added new syntax for performing array updates that would allow you to express the query as you wish. Although SERVER-18500 remains an open issue, we encourage users to migrate to this new syntax. This will soon be available in the upcoming 3.6.0 stable release. See SERVER-27089 for details. I believe that you could write your query as follows in 3.6:

db.mongo.update({a: NumberInt(456)},
                {$addToSet: {"b.c.$[i].f": {"x": NumberInt(1), "y": NumberInt(2)}}},
                {arrayFilters: [{"i.d": NumberInt(10), "i.e": NumberInt(24)}]})

I am going to resolve as a duplicate of SERVER-18500, but please let me know if you have any further questions or concerns.

Best,
Dave

Comment by Henri-Maxime Ducoulombier [ 08/Sep/17 ]

This may be linked to SERVER-27738

And a "fix" seems to have been commited but reverted by commit :
https://github.com/mongodb/mongo/commit/5c3f83de911a2d7a512954349925b3c6056b886e

(which also means SERVER-27738 shouldn't be resolved/closed but reopen).

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