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?
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)
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
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
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.