何时使用嵌入式文档?

时间:2010-01-03 00:15:48

标签: mongodb mongomapper

我正在试图找出如何为我正在处理的网站布置数据库。这是我的模特:

class User
  include MongoMapper::Document

  // keys here

  many :items
  many :likes
end

class Item
  include MongoMapper::Document

  key :name, String, :required => true

  many :likes
end

class Like
  include MongoMapper::EmbeddedDocument

  key :user_id, String, :required => true
end

我相信Like应该嵌入某个地方,但由于我希望摆脱它的功能,我很难选择一个。

user = User.first
user.likes // should print out all the Items he liked

item = Item.first
item.likes // so I can count how many people like that item

虽然使用EmbeddedDocument时会出现问题,但您会丢失find和其他有用的方法,并且无法在两个模型中嵌入它。所以只在Item中使用它,我需要运行它(但不能):

item = Item.first
item.likes.find_by_user_id(User.first._id)

将抛出未定义的方法find_by_user_id。因此,如果我要将其嵌入User,我仍然无法做到这一点。

likes = Like.all // will throw undefined `all`

所以我开始考虑这样做:

class Like
  include MongoMapper::Document

  key :user_id, String, :required => true
  key :item_id, String, :required => true

  belongs_to :user
  belongs_to :item
end

但这似乎我仍在尝试用旧的MySQL方式做事。有人能用最有可能的方式给我一点用MongoMapper来编码吗?

提前致谢!

2 个答案:

答案 0 :(得分:9)

是否可以在MongoMapper中对此进行建模取决于是否需要将数据存储在Like模型中。如果在您的示例中没有与Like模型关联的任何数据,则有一种方法。对MongoMapper的最新更新增加了对多对多关系的支持,尽管它仍处于早期阶段。

您可以像这样创建模型:

class User
  include MongoMapper::Document
  key :name, String, :required => true
  key :liked_item_ids, Array
  many :liked_items, :in => :liked_item_ids, :class_name => "Item"
end

class Item
  include MongoMapper::Document
  key :name, String, :required => true
  many :fans, :class_name => "User", :foreign_key => :liked_item_ids
end

然后你可以这样做:

>> u = User.new( :name => 'emily' )
>> i = Item.new( :name => 'chocolate' )
>> u.liked_items << i
>> u.save
>> u.liked_items
=> [#<Item name: "chocolate", _id: 4b44cc6c271a466269000001>]

>> i.fans
=> [#<User name: "emily", liked_item_ids: [4b44cc6c271a466269000001], _id: 4b44cc6c271a466269000002>]

不幸的是,使用此设置无法做到的是从关系的Item侧添加类似内容。但是,在GitHub上有一个关于为many :in关系创建正确反向的问题,在这个例子中将使用如下:

many :fans, :class_name => "User", :source => :liked_items

另一方面,如果有需要存储在Like中的信息,例如用户喜欢该项目的日期,则目前无法对其进行建模。在这种情况下,理想的设置(忽略MongoMapper现在支持的内容)与您在问题中包含的内容类似。您需要所有三个模型,Like模型中嵌入Userhas_many :through关系,以创建从UserItem的链接。不幸的是,在MongoMapper中对此的支持可能相当遥远。

如果您想在MongoMapper中鼓励支持此类行为,您可以在mailing list上询问此问题或在MongoMapper github repository上打开问题。

答案 1 :(得分:3)

您可能需要阅读mongodb.org上的文档“嵌入与参考”:http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-Embedvs.Reference