使用Mongoid,假设我有以下类:
class Map
include Mongoid::Document
embeds_many :locations
end
class Location
include Mongoid::Document
field :x_coord, :type => Integer
field :y_coord, :type => Integer
embedded_in :map, :inverse_of => :locations
end
class Player
include Mongoid::Document
references_one :location
end
正如您所看到的,我正在尝试建立一个简单的游戏世界环境,其中地图嵌入位置,并且玩家将单个位置作为当前位置。
使用这种方法,当我尝试引用Player类的“location”属性时,我收到以下错误:
Mongoid::Errors::DocumentNotFound: Document not found for class Location with id(s) xxxxxxxxxxxxxxxxxxx.
我的理解是,这是因为位置文档是嵌入式的,因此很难在其嵌入文档(Map)的范围之外引用。这是有道理的,但我如何建模直接引用嵌入式文档?
答案 0 :(得分:17)
因为地图是他们自己的集合,所以您需要遍历搜索引擎所在位置的每个地图集合。
您无法直接访问嵌入式文档。你必须通过这个系列进入并按照你的方式工作。
为避免迭代所有地图,您可以在Player文档中存储位置参考和地图参考。这允许您链接选择Map的条件,然后选择其中的位置。您必须在Player类上编写一个方法来处理这个问题。
def location
self.map.locations.find(self.location_id)
end
所以,类似于你自己的回答,除了你仍然可以将location_id存储在你的播放器文档中,而不是使用coord attribs。
另一种方法是将地图,位置和播放器放在他们自己的集合中,而不是在Map集合中嵌入Location。然后你可以使用引用关系而不做任何花哨的事情......但是你真的只是使用分层数据库就像它在这一点上的关系数据库......
答案 1 :(得分:11)
请继续投票选择MongoDB问题跟踪器上的“虚拟馆藏”功能:
http://jira.mongodb.org/browse/SERVER-142
这是第二个要求最多的功能,但它仍未安排发布。也许如果有足够多的人投票支持它并将其转移到第一,MongoDB团队将最终实施它。
答案 2 :(得分:6)
在我的用例中,外部对象不需要引用嵌入的文档。从mongoid用户组,我找到了解决方案:在嵌入文档上使用referenced_in,在外部文档上使用NO引用。
class Page
include Mongoid::Document
field :title
embeds_many :page_objects
end
class PageObject
include Mongoid::Document
field :type
embedded_in :page, :inverse_of => :page_objects
referenced_in :sprite
end
class Sprite
include Mongoid::Document
field :path, :default => "/images/something.png"
end
header_sprite = Sprite.create(:path => "/images/header.png")
picture_sprte = Sprite.create(:path => "/images/picture.png")
p = Page.create(:title => "Home")
p.page_objects.create(:type => "header", :sprite => header_sprite)
p.page_objects.first.sprite == header_sprite
答案 3 :(得分:0)
我目前的解决方法是执行以下操作:
class Map
include Mongoid::Document
embeds_many :locations
references_many :players, :inverse_of => :map
end
class Player
referenced_in :map
field :x_coord
field :y_coord
def location=(loc)
loc.map.users << self
self.x_coord = loc.x_coord
self.y_coord = loc.y_coord
self.save!
end
def location
self.map.locations.where(:x_coord => self.x_coord).and(:y_coord => self.y_coord).first
end
end
这很有效,但感觉就像一个kluge。
答案 4 :(得分:0)
在盒子外面思考,您可以将Location设置为自己的文档,并使用Mongoid Alize从您的位置文档中自动生成Map文档中的嵌入数据。
https://github.com/dzello/mongoid_alize
这种方法的优点是,当条件合适时,您可以获得高效的查询,而当没有其他方法时,您可以在原始文档上获得较慢的基于参考的查询。