John Labovitz
John Labovitz

Reputation: 156

How to do atomic update in Mongo/Mongomatic?

I'm having an awfully difficult time figuring out how to update a MongoDB document, using the atomic '$set' operator with Mongomatic. I'm pretty sure it's Mongo's criteria/update language I'm having troubles with, not Mongomatic, but I'm willing to be proven wrong.

The link to a gist with a standalone, runnable script is here: https://gist.github.com/3835672

I'm starting out by creating a document that looks like this:

{"videos":[{"video_id":"video1"},{"video_id":"video2"}],"_id":{"$oid": "506ddd53a114604ce3000001"}}

I can get that document using a model instantiated using Mongomatic:

video_group = VideoGroup.find_one('videos.video_id' => 'video1')

Then I'm trying to set a 'views' field, by doing this:

video_group.update!({ 'videos.video_id' => 'video1' }, '$set' => { 'videos.$.views' => 123 })

That's where Mongo blows up, with the following error:

can't append to array using string field name [$]

I know this is a very common question on StackOverflow. I understand generally that the problem is that the positional operator isn't getting any matches. But even reading through dozens of responses, I still can't figure out how to express this statement in a way that works.

Am I just starting out with the wrong data structure?

Upvotes: 1

Views: 183

Answers (1)

Steve Y
Steve Y

Reputation: 343

It is, in fact, a mongomatic problem. You need to pass the underlying mongo ruby driver the option {:multi => true}, as well as including your criteria with the specific _id for the update sent to mongodb instead of as part of the optional parameters. Looks like a bug in mongomatic. Here is the ruby debugger transcript that I used to find it: https://gist.github.com/3836797

Note that I made a change to the file you posted, adding the line debugger before line #41, and changing line #42-44 to this:

video_group.update!({ 'videos.video_id' => 'video1', :multi => true }, '$set' => {
  'videos.$.views' => 123,
})

Upvotes: 1

Related Questions