Question

Definitely related to this question, but since there was no clear answer, I feel like I should ask again. Is there any way to remove an embedded document from a Mongoid embeds_many relationship, without persisting?

I want to modify the array of embedded documents in-memory - and then persist all changes with a single UPDATE operation. Specifically, I'd like to:

  1. Modify arrays of embedded documents (add embedded doc / remove embedded doc / edit embedded doc / etc).
  2. Possibly make other changes to the TLD.
  3. Persist all changes with a single database call.
Était-ce utile?

La solution

It is possible to remove an embedded document using Mongoid without saving. The trick is to make your changes from the parent object using assign_attributes. For exmaple:

class MyParent
  include Mongoid::Document

  field :name, type: String
  embeds_many :my_children

  def remove_my_child(child)
    assign_attributes(my_children: my_children.select { |c| c != child })
  end
end

class MyChild
  include Mongoid::Document

  embedded_in :my_parent

  def remove
    parent.remove_my_child(self)
  end
end

my_parent = MyParent.first
my_first_child = my_parent.my_children.first

# no mongo queries are executed
my_first_child.remove

# now we can make another change with no query executed
my_parent.name = 'foo'

# and finally we can save the whole thing in one query which is the
# reason we used an embedded document in the first place, right?
my_parent.save!

Autres conseils

After two more years of using Mongoid, I've learned there's no operator for what I was trying to achieve. Removing an embedded document with Mongoid always results in a database call.

In situations like this one, it's easier to bypass Mongoid and use the mongo-ruby-driver directly.

Try mongoid's

update_all()

Documentation

Ex: If I wanted to make all my users Joe

User.update_all(name: 'Joe')

will behave exactly as you would expect.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top