Mongoid:查询嵌入式(recursively_embeds_many)文档

时间:2013-01-17 01:03:33

标签: ruby-on-rails mongoid

如何查找符合我标准的所有文档,与文档嵌入的深度无关?

假设我有一个使用* recursively_embeds_many *的模型。例如,可以回复的评论。回复,可以有另一个回复等等。

class Comment
  include Mongoid::Document
  field :content, type: String
  recursively_embeds_many # this makes comment.child_comments available
end

所以结构基本上是:

  • 注释
    • content(string)
    • 评论(评论列表)

如何查询内容等于“foo”的所有评论文档?

1 个答案:

答案 0 :(得分:3)

此解决方案使用Mongodb点表示法查询与$or组合来提取相关注释,然后遍历它们。您必须指定最大递归级别。

请不要在现场制作中使用任何东西!如果您使数据库崩溃,我不想要负责:​​P

# app/models/comment.rb
class Comment
  include Mongoid::Document
  field :content, type: String
  recursively_embeds_many # this makes comment.child_comments available

  # 'n' is the maximum level of recursion to check.
  def self.each_matching_comment(n, q, &block)
    queries = 0.upto(n).collect { |l| level_n_query(l, q) }
    Comment.or(*queries).each { |c| c.each_matching_subcomment(q, &block) }
  end

  def self.level_n_query(n, q)
    key = (['child_comments'] * n).join('.') + 'content'
    return {key => q}
  end

  # recursive, returns array of all subcomments that match q including self
  def each_matching_subcomment(q, &block)
    yield self if self.content == q
    self.child_comments.each { |c| c.each_matching_subcomment(q, &block) }
  end
end

# hits each comment/subcomment up to level 10 with matching content once
Comment.each_matching_comment(10, 'content to match') do |comment|
  puts comment.id
end

如果您希望这样做更快,您应该在评论和子评论上构建索引。