[SERVER-24340] positional $ operator update fails without match from query document Created: 01/Jun/16  Updated: 19/Dec/16  Resolved: 02/Jun/16

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

Type: Bug Priority: Major - P3
Reporter: Alex Chaffee Assignee: Kelsey Schubert
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Steps To Reproduce:

Given docs with this structure (from docs created using MongoEngine {{EmbeddedDocument}}s ):

{
        ...
	"status_history" : [
		{
			"_types" : [
				"EntityStatus"
			],
                        ... 

Running this on the console:

> db.entities.update({}, {'$unset': {'status_history.$._types': true}}, {'multi': true})
WriteResult({
	"nMatched" : 0,
	"nUpserted" : 0,
	"nModified" : 0,
	"writeError" : {
		"code" : 16837,
		"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: status_history.$._types"
	}
})
> db.entities.update({}, {'$unset': {'status_history.0._types': true}}, {'multi': true})
WriteResult({ "nMatched" : 1570, "nUpserted" : 0, "nModified" : 1179 })

Participants:

 Description   
Original summary

$unset with positional $ fails to find nested field

Original Description

In a database with documents with a list of nested documents $unset does not match all elements in that list as expected.

A query like this

 db.entities.update({}, {'$unset': {'status_history.$._types': true}}, {'multi': true}) 

should completely remove all `_types` entries from all `status_history` items from all `entities` docs (or at least not fail).

...although the mongo manual at https://docs.mongodb.com/manual/reference/operator/update/positional/#unsets states "When used with the $unset operator, the positional $ operator does not remove the matching element from the array but rather sets it to null." which sounds like a flaw, not a desirable feature, but that's a different issue.



 Comments   
Comment by Kelsey Schubert [ 02/Jun/16 ]

Hi codelikethis,

The behavior you describe is expected. The array field must appear as a part of the query document. Since there is no array in your query, MongoDB cannot identify a match for the value of the positional operator.

I'd also like to clarify that the positional $ operator acts a placeholder for the first match of the update query document. Please see the example below:

> db.foo.insert({subDocuments:[{x:1,y:1},{x:1,y:2},{x:1,y:3}]})
WriteResult({ "nInserted" : 1 })
> db.foo.update({'subDocuments.x':1},{$unset:{'subDocuments.$.y' : true}}, {multi : true})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.foo.find()
{ "_id" : ObjectId("574eff3cf239c58a6d6fa039"), "subDocuments" : [ { "x" : 1 }, { "x" : 1, "y" : 2 }, { "x" : 1, "y" : 3 } ] }

Please note that SERVER project is for reporting bugs or feature suggestions for the MongoDB server. For MongoDB-related support discussion please post on the mongodb-users group or Stack Overflow with the mongodb tag. A question like this involving more discussion would be best posted on the mongodb-users group.

Kind regards,
Thomas

Comment by Alex Chaffee [ 01/Jun/16 ]

in "steps to reproduce" i listed two commands; the first fails but the second succeeds, showing that using a number for position works but using $ fails, which is wrong, since $ should match anything a numeric index does and then some

Comment by Alex Chaffee [ 01/Jun/16 ]

...ugh, I can't edit the description to clean up the formatting... thanks, jira

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