1

I got the following document

{ a: { b: { c1: 1, c2: 2 } } }

I want to atomically modify only c1 to 8

I do document.set('a.b.c1': 8), but entire value of 'b' changes to {c1:8}.

this is my class

class C
  include Mongoid::Document
  field :a, type: Hash 
end

why is that?

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
Chen Kinnrot
  • 20,609
  • 17
  • 79
  • 141
  • 1
    Show the code how you defined the model. – Neil Lunn Jun 21 '17 at 11:12
  • How about turning on logging and seeing what the actual request to MongoDB is. This post seems to have a plausible instruction: https://coderwall.com/p/dz6ttq/log-mongoid-queries-inline-in-rails-console – Neil Lunn Jun 21 '17 at 11:20
  • 1
    @NeilLunn: yeah, I reproduced. It does indeed do `"$set"=>{"a"=>{"b"=>{"c1"=>3}}}`. Weird – Sergio Tulentsev Jun 21 '17 at 11:22
  • The question is tagged as Mongoid 5 did you use that as well @SergioTulentsev? – Neil Lunn Jun 21 '17 at 11:23
  • Ouch! Bug confirmed https://jira.mongodb.org/browse/MONGOID-4254 – Neil Lunn Jun 21 '17 at 11:24
  • @NeilLunn: yep, I did. – Sergio Tulentsev Jun 21 '17 at 11:25
  • Don't have a quick ruby env to spin up at the moment. But the JIRA issue seems to have the workaround (use the `.collection` accessor to moped basically). The bug is fixed v6.0,1 as mentioned, but I don't know about backports. Someone as been lax updating the [CHANGELOG on the git repo](https://github.com/mongodb/mongoid). Grr! – Neil Lunn Jun 21 '17 at 11:39

1 Answers1

3

It seems to be a bug in Mongoid 5 (as found by Neil). Here's how you can sidestep this for now (until you upgrade):

C.where(id: object_id).update('a.b.c1' => 5)

There's an alternative workaround in the linked jira ticket.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367