Mongoid find embedded document

2019-07-31 14:08发布

I'm trying to search for an embedded document by its id, and return it. This is possible, but only, as far as I see, by using mongo to find the document which embeds it, and then searching that document in ruby for the embedded document I'm after. Like this:

# commenter.rb
  def post
    # todo: find syntax do avoid double query
    if user = User.any_of({'posts.commenter_ids' => self.id}).last
      user.posts.where('commenter_ids' => self.id).last
    end
  end

Seems simple, but I haven't found anything I like obviously on google/SO search.

Thoughts?

4条回答
SAY GOODBYE
2楼-- · 2019-07-31 14:36

Right now I am including the following functionality into my embedded documents. It requires that you set the inverse_of option on the nested relationship.

# Returns the parent "embedded_in" relationship for this document
# @return [Mongoid::Relations::Metadata]
def self.parent_relationship
  @parent_relationship ||= relations.values.find do |relation|
    relation.macro == :embedded_in
  end
end

# finds the document off of a root document. This method currently only works correctly if
# you explicitly set the inverse_of value on the embedded_in relationship
# @param [string | Moped::BSON::ObjectId] id
def self.find_using_parent(id)
  id = id.is_a?(Moped::BSON::ObjectId) ? id : Moped::BSON::ObjectId(id)
  parent = parent_relationship.class_name.to_const.where("#{parent_relationship.inverse_of}._id" => id).first
  if parent
    parent.__send__(parent_relationship.inverse_of).find(id)
  end
end
查看更多
SAY GOODBYE
3楼-- · 2019-07-31 14:46

You can't find a resource without the document it embeds. If you just want a relationship between the two instead of embedding it, you should use has_many instead of embeds_many http://mongoid.org/en/mongoid/docs/relations.html#has_many. You can then find the document without it's related document.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-07-31 14:57

I override find method on my embedded documents using this gist: https://gist.github.com/cblavier/7889042

It's especially convenient when I want to use DelayedJob to delay embedded document methods (because DJ worker will use find(id) to deserialize the job)

查看更多
Rolldiameter
5楼-- · 2019-07-31 14:59
class Order
  embeds_many Products
end

class Product
  embedded_in Order
end

prod_id = "1234" # the embedded doc's _id you request
o = Order.find(product_ids: prod_id)
p = o.products.find(prod_id)

See also Does querying Mongoid embedded documents hit the database server after loading a parent document

查看更多
登录 后发表回答