2013-01-17 47 views
1

如何找到符合我的標準的所有文檔,而不管文檔嵌入文檔的深度如何?Mongoid:查詢嵌入(recursively_embeds_many)文件

假設我有一個使用* recursively_embeds_many *的模型。例如,可以有回覆的評論。答覆,可以有另一個答覆等。

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

所以結構基本上是:

  • 評論
    • 內容(串)
    • 評論(評論列表)

我怎樣才能詢問對於內容等於「foo」的所有評論文件

回答

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 

,如果你想這得更快,您應該建立在你的意見和subcomments指標。