Frage

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.
War es hilfreich?

Lösung

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!

Andere Tipps

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top