mongoid / moped

A MongoDB driver for Ruby
https://mongoid.github.io/old/en/moped/
MIT License
201 stars 153 forks source link

moped update_all doesn't update_all #147

Closed ckhall closed 11 years ago

ckhall commented 11 years ago

using moped via Mongoid.default_session, when I try to update_all, it's not updating any of the records. after some sleuthing, I'm thinking this is related to my version of mongdb.

mongodb 2.0.2 mongoid 3.0.18 moped 1.3.2

console:

irb(main):067:0> Mongoid.default_session['some_collection'].find(some_id: { '$ne' => nil}).count
  MOPED: 127.0.0.1:27017 COMMAND      database=test_db command={:count=>"some_collection", :query=>{:some_id=>{"$ne"=>nil}}}
=> 9
irb(main):068:0> Mongoid.default_session['some_collection'].find(some_id: { '$ne' => nil}).update_all(some_id: nil)
MOPED: 127.0.0.1:27017 UPDATE       database=test_db collection=some_collection selector={:some_id=>{"$ne"=>nil}} update={:some_id=>nil} flags=[:multi]
=> nil
irb(main):069:0> Mongoid.default_session['some_collection'].find(some_id: { '$ne' => nil}).count
  MOPED: 127.0.0.1:27017 COMMAND      database=test_db command={:count=>"some_collection", :query=>{:some_id=>{"$ne"=>nil}}}
=> 9

I see the flags=[:multi] is set, so I would think that it would update the records, but it did not update any of them

mongodb log (associated with above update_all method):

update test_db.some_collection query: { some_id: { $ne: null } } update: { some_id: null }

I see here that nothing related to multi is mentioned in the log output, but even then, I would have expected at least one record to have been updated.

I then tried it out in the shell

mongo shell:

> db.some_collection.find({some_id: { $ne: null}}).count()
9
> db.some_collection.update({some_id: {$ne : null}}, {$set: {some_id: null}}, {multi: true})
> db.some_collection.find({some_id: { $ne: null}}).count()
8

the above didn't work as expected, it only updated one record. but it DID update something

> db.some_collection.update({ some_id: {$ne : null}}, {$set: {some_id: null}}, false, true)
> db.some_collection.find({some_id: { $ne: null}}).count()
0

this one did work, so I figured it had to do with my version of mongodb and {multi: true} not being an option in in 2.0.2

either way, the update_all didn't work at all. I also tried enumerating through the queried records and calling update(some_id: nil) on them, but that did not work either.

chrisnicola commented 11 years ago

Having the same problem right now.

darrencauthon commented 11 years ago

Third.

suweller commented 11 years ago

I had similar problems with embedded documents on which I called: delete_all. I solved this (for embedded documents) by simple emptying the array containing the documents I wanted to delete.

parent.update_attributes(:children => [])

we use: mongod 2.0.5 mongoid 3.1.1 moped 1.4.2

durran commented 11 years ago

The problem is your update query - you aren't telling it to $set the values... The query should be:

Mongoid.default_session['some_collection'].find(some_id: { '$ne' => nil}).update_all("$set" => { some_id: nil })

If you did the query from Mongoid, then it is smart enough to convert to $set values if you don't provided, but Moped isn't.

Model.where(:some_id.ne => nil).update_all(some_id: nil)
darrencauthon commented 11 years ago

Ah, makes sense.

I had switched to using "$set" on my moped calls, for obvious reasons -- should have known that would be it.

Thanks!

ckhall commented 11 years ago

fair enough, but according to the documentation for Query#update_all at http://mongoid.org/en/moped/docs/driver.html

the example is:

query.update_all(pending: true)

not

query.update_all("$set" => { pending: true })

so perhaps the documentation should reflect that?

chrisnicola commented 11 years ago

:+1:

durran commented 11 years ago

@ckhall Sorry for the documentation error, will get that fixed.