Reputation: 156
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
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