Mongoid很多很多问题

时间:2010-11-08 06:05:29

标签: ruby-on-rails mongodb 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

2 个答案:

答案 0 :(得分:4)

您可以使用Tag上的方法绕过它来伪造关联的另一面

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方法。

对于许多现实世界的情况,这种方法是实用的,只要你保持方法简单并且不会被带走。

答案 1 :(得分:2)

Map Reduce可能是您的答案。查看MongoDB map reduce并使用标签的永久集合输出

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,values},其中{:id =&gt; TAGNAME,:value =&gt; {:count =&gt; NUMBER_OF_TIMES_TAG_IS_USED,:posts =&gt; [ARRAY_OF_BLOG_ARTICLES]}} 您可以创建formatl Tag类或使用:

Mongoid.master.collection("tags")

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