2010-11-08 83 views
2

我想將博客及其標籤存儲爲單獨的文檔。Mongoid多對多問題

博客文章應該有tag_ids字段和標籤不應該有blog_posts_ids字段。

Mongoid提供了許多開箱即用的關係,但它需要多對多關係的文檔都有_ids字段。

class BlogPost 
    include Mongoid::Document 
    field :title 
    references_many :tags, :stored_as => :array, :inverse_of => :blog_posts 
end 

class Tag 
    include Mongoid::Document 
    field :name 
    # I DON'T WANT TO STORE BLOG_POSTS_IDS IN TAG DOCUMENT 
    references_many :blog_posts, :stored_as => :array, :inverse_of => :tags 
end 
+0

誰不能用mongoid代碼。創建你自己的方法。 – shingara 2010-11-08 08:29:52

回答

4

你可以繞過它的方法僞造的另一面:帖=> [ARRAY_OF_BLOG_ARTICLES]}} 您可以創建一個formatl標籤類或使用協會

class BlogPost 
    include Mongoid::Document 
    field :title 
    references_many :tags, :stored_as => :array, :inverse_of => :blog_posts 
end 

class Tag 
    include Mongoid::Document 
    field :name 

    def blog_posts 
    # will match all BlogPost records where the tag_ids array contains self.id 
    BlogPost.where(:tag_ids => self.id) 
    end 
end 

很顯然,這並不是全功能爲:references_many,但你可以在很多一對多關係的類似假冒其他方面。例如,如果您希望能夠爲標籤分配新的blog_post,則可以將簡單的create_blog_post方法添加到Tag

對於很多現實世界的情況,只要保持方法簡單並且不會被帶走,這種方法就是實用的。

2

地圖減少可能是你的答案。看看到MongoDB的映射減少和使用永久收藏輸出標籤

class BlogPost 
    include Mongoid::Document 
    field :title 
    field :tags, :type => Array 
    references_many :tags, :stored_as => :array, :inverse_of => :blog_posts 
end 

map =<<JS 
    function(){ 
    if(!this.tags){ 
     return; 
    } 
    for(index in this.tags){ 
     emit(this.tags[index],{count:1,posts:[this.post.id]}) 
    } 
    } 
JS 

reduce =<<JS 
    function(key,values){ 
    var tagging = {count:0,posts:new Array()} 
    values.forEach (function(val) { 
     tagging.count++; 
     tagging.posts.push(val.posts[0]) 
    }); 
    return tagging; 
    } 
JS 

BlogPost.collection.map_reduce(map,reduce,{:out => 'tags',:keeptemp => true}) 

結果集總是{ID,值}其中{:ID =>標記名:價值=> {:數=> NUMBER_OF_TIMES_TAG_IS_USED ,:在Tag

Mongoid.master.collection("tags") 

http://api.mongodb.org/ruby/1.1.2/Mongo/Collection.html#map_reduce-instance_methodt