[SERVER-2250] CLONE -$in operator for behaves unexpected on upserts Created: 19/Dec/10  Updated: 07/Mar/14  Resolved: 19/Dec/10

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

Type: Bug Priority: Major - P3
Reporter: andrew luetgers Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

any


Operating System: ALL
Participants:

 Description   

We would like to reduce the number of updates by using the $in operator going from

buckets = [ '2010', '2010-08', '2010-08-01' ]
buckets.each do |bucket|
@totals.update(

{ 'bucket' => bucket }

, { '$inc' => { 'downloads' => 1 }}, :upsert => true)
end

to

buckets = [ '2010', '2010-08', '2010-08-01' ]
@totals.update({ 'bucket' =>

{ "$in" => buckets }

}, { '$inc' => { 'downloads' => 1 }}, :upsert => true)

Unfortunately we get very strange and inconsistent results.

db.test.find()
db.test.update(

{"b": 2}

, { "$inc":

{ "d": 1 }

}, true)
db.test.find()

{ "_id" : ObjectId("4c6d1e345153667a3fd349b8"), "b" : 2, "d" : 1 }

db.test.update(

{"b": 3}

, { "$inc":

{ "d": 1 }

}, true)
db.test.find()

{ "_id" : ObjectId("4c6d1e345153667a3fd349b8"), "b" : 2, "d" : 1 } { "_id" : ObjectId("4c6d1e485153667a3fd349b9"), "b" : 3, "d" : 1 }

db.test.update({"b":

{ "$in": [ 2, 3, 4 ] }

}, { "$inc":

{ "d": 1 }

}, true)
db.test.find()

{ "_id" : ObjectId("4c6d1e345153667a3fd349b8"), "b" : 2, "d" : 2 } { "_id" : ObjectId("4c6d1e485153667a3fd349b9"), "b" : 3, "d" : 1 }

We would expect also

{ "_id" : ObjectId("4c6d1e485153667a3fd349ba"), "b" : 4, "d" : 1 }

to be there. Then we found there is 'multi' option to turn on in (from http://www.mongodb.org/display/DOCS/Updating )

"multi - if all documents matching criteria should be updated"

But that still does not create a documents as expected.

db.test.update({"b":

{ "$in": [ 2, 3, 4 ] }

}, { "$inc":

{ "d": 1 }

}, true, true)
db.test.find()

{ "_id" : ObjectId("4c6d1e345153667a3fd349b8"), "b" : 2, "d" : 3 } { "_id" : ObjectId("4c6d1e485153667a3fd349b9"), "b" : 3, "d" : 2 }

Now even more weird. Trying again it does create a document - but not the one expected:

db.test.update({"b":

{ "$in": [ 55, 66 ] }

}, { "$inc":

{ "d": 1 }

}, true, true)
db.test.find()

{ "_id" : ObjectId("4c6d1e345153667a3fd349b8"), "b" : 2, "d" : 3 } { "_id" : ObjectId("4c6d1e485153667a3fd349b9"), "b" : 3, "d" : 2 } { "_id" : ObjectId("4c6d1f1a5153667a3fd349ba"), "d" : 1 }

What are we missing here?



 Comments   
Comment by Eliot Horowitz (Inactive) [ 19/Dec/10 ]

This is correct behavior.

When you specify a non-specify query option $in, $gt, $or, etc... we do not create every possible combination.

With $gt is actually impossible, so we want to make keep it consistent.

Also, mixing upsert and updates is not a great idea as well.

Comment by andrew luetgers [ 19/Dec/10 ]

sorry that last example does upsert this is the one that doesnt

update({ token:

{ $in: ["@adan", "@ken", "@loot"] }

, category: "default" }, { $inc:

{count: 1}

}, true, true);

Comment by andrew luetgers [ 19/Dec/10 ]

i cloned this becasue i want to voice my support for multi upserts, if they could simple be limited to the cases that make sense, then they would be very useful for example i want to keep track of how often each token is used so id like to simply multi-upsert with $inc like so

db.tokens.update(

{ token: "@ken", category: "default" }

, { $inc:

{count: 1}

}, true, true);

this will not upsert, but there is no reason that this particular update shouldnt work

Generated at Thu Feb 08 02:59:24 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.