Как ссылаться на встроенный документ в Mongoid?

StackOverflow https://stackoverflow.com/questions/3890633

  •  28-09-2019
  •  | 
  •  

Вопрос

Использование монгоида, скажем, у меня есть следующие классы:

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

Как видите, я пытаюсь моделировать простую игровую мировую среду, где карта встраивает местоположения, а игрок ссылается на одно местоположение как их текущее место.

Используя этот подход, я получаю следующую ошибку, когда я пытаюсь ссылаться на атрибут «местоположения» класса плеера:

Mongoid::Errors::DocumentNotFound: Document not found for class Location with id(s) xxxxxxxxxxxxxxxxxxx.

Мое понимание состоит в том, что это потому, что документ местоположения встроен, что затрудняет ссылку за пределами объема его встраиваемого документа (карта). Это имеет смысл, но как мне представить прямую ссылку на встроенный документ?

Это было полезно?

Решение

Поскольку карты являются их собственной коллекцией, вам нужно будет повторять каждую коллекцию карты в поисках внутри местонахождения, на который ссылается, на который ссылается ваш игрок.

Вы не можете получить доступ к встроенным документам напрямую. Вы должны войти через коллекцию и работать вниз.

Чтобы избежать итерации всех отображений, вы можете хранить как ссылку на местоположение, так и ссылку на карту в документе вашего игрока. Это позволяет вам цепи критерии, которые выбирают вашу карту, а затем местоположение внутри него. Вы должны кодировать метод в классе вашего игрока, чтобы обработать это.

def location
  self.map.locations.find(self.location_id)
end

Итак, похоже на то, как вы ответили на себя, за исключением того, что вы все равно можете хранить местоположение_id в своем документе Player, а не использовать атрибуты координат.

Еще один способ поставить карты, места и игроки в свои собственные коллекции вместо того, чтобы встроить местоположение в вашей карте. Тогда вы можете использовать ссылочные отношения, не делая ничего фантазии ... Однако вы действительно просто используете иерархическую базу данных, это нравится реляционная база данных в этой точке ...

Другие советы

Пожалуйста, проготайте и голосуйте за функцию «Виртуальные коллекции» на выпуске MongoDB Tracker:

http://jira.mongodb.org/browse/server-142.

Это 2-я самая запрошенная функция, но она все еще не была запланирована для выпуска. Может быть, если достаточно людей проголосуют за это и переместите его на номер один, команда MongoDB, наконец, будет реализовать ее.

В моем случае в случае использования внешнего объекта нет необходимости ссылаться на встроенный документ. Из группы пользователей Mongoid я нашел решение: используйте ссылку на ссылку на встроенный документ и без ссылки на внешний документ.

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

Мой текущий обходной путь состоит в том, чтобы сделать следующее:

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.

Думая за пределами коробки, вы можете создать местоположение собственным документом и использовать Mongoid Alize, чтобы автоматически генерировать встроенные данные в документ вашей карты из ваших документов о местоположении.

https://github.com/dzello/mongoid_alize.

Преимущество этого метода заключается в том, что вы получаете эффективные запросы, когда условия подходят, и более медленные ссылочные запросы на исходном документе, когда нет другого способа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top