Как ссылаться на встроенный документ в Mongoid?
Используя 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
Как вы можете видеть, я пытаюсь смоделировать простую игровую мирную среду, где карта включает в себя местоположения, а игрок ссылается на одно место в качестве своего текущего места.
Используя этот подход, я получаю следующую ошибку, когда пытаюсь ссылаться на атрибут "location" класса Player:
Mongoid::Errors::DocumentNotFound: Document not found for class Location with id(s) xxxxxxxxxxxxxxxxxxx.
Я понимаю, что это связано с тем, что документ местоположения встроен, что затрудняет ссылку за пределы его документа внедрения (Карта). Это имеет смысл, но как я могу моделировать прямую ссылку на встроенный документ?
Ответы
Ответ 1
Поскольку Maps - это их собственная коллекция, вам нужно будет перебирать каждый поиск коллекции карт внутри местоположения, на которое ссылается ваш плеер.
Вы не можете напрямую обращаться к встроенным документам. Вы должны войти в коллекцию и проложить свой путь.
Чтобы избежать повторения всех Карт, вы можете сохранить как ссылку "Место", так и ссылку "Карта" в документе "Игрок". Это позволяет вам привязать критерии, которые выбирают вашу карту, а затем местоположение внутри нее. Вы должны закодировать метод в своем классе Player, чтобы справиться с этим.
def location
self.map.locations.find(self.location_id)
end
Итак, похоже на то, как вы ответили сами за себя, кроме того, что вы сохранили location_id в документе вашего игрока вместо использования атрибутов кодов.
Другим способом было бы поместить Карты, местоположения и игроки в свои собственные коллекции, а не встраивать местоположение в вашу коллекцию карт. Тогда вы могли бы использовать ссылочные отношения, не делая ничего необычного... однако на самом деле, просто используя иерархическую базу данных, она нравится реляционной базе данных на этом этапе...
Ответ 2
ПОЖАЛУЙСТА, и VOTE для функции "виртуальных коллекций" в отслеживателе проблем MongoDB:
http://jira.mongodb.org/browse/SERVER-142
Это вторая самая запрошенная функция, но она еще не была запланирована для выпуска. Может быть, если достаточно людей проголосуют за него и переведут его на номер один, команда MongoDB, наконец, выполнит его.
Ответ 3
В моем случае использования внешнему объекту не требуется ссылаться на встроенный документ. Из группы пользователей mongoid я нашел решение: используйте ссылочный_индекс во встроенном документе и ссылку 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
Ответ 4
Мое текущее обходное решение заключается в следующем:
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.
Ответ 5
Мышление вне поля, вы можете сделать свой собственный документ и использовать Mongoid Alize для автоматического создания встроенных данных в вашем документе карты из ваших документов местоположения.
https://github.com/dzello/mongoid_alize
Преимущество этого метода заключается в том, что вы получаете эффективные запросы, когда подходят условия, и медленные запросы на основе ссылок на исходный документ, когда нет другого пути.