22 votos

Cómo hacer referencia a un documento incrustado en Mongoid?

El uso de Mongoid, digamos que tengo las siguientes clases:

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

Como puedes ver, estoy tratando de modelar un simple juego mundial del medio ambiente, donde un mapa incrusta lugares, y un jugador que hace referencia a una única ubicación como su actual lugar.

Con este enfoque, me da el siguiente error cuando trato de hacer referencia a la "ubicación" atributo de la clase de Jugador:

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

Mi entendimiento es que esto es debido a que el documento de Ubicación está incrustado lo que es difícil de referencia de fuera del ámbito de su incrustación de objetos de documento (el Mapa). Esto tiene sentido, pero ¿cómo puedo modelo de una referencia directa a un documento incrustado?

17voto

Dave Rapin Puntos 1136

Porque los Mapas son de su propia colección, usted necesita para iterar sobre cada colección de Mapas de la búsqueda dentro de la Ubicación de su Jugador de referencia.

Usted no puede tener acceso a los documentos incrustados directamente. Tienes que entrar a través de la colección y su forma de trabajo hacia abajo.

Para evitar recorrer todos los Mapas, se puede almacenar la referencia de Ubicación Y el Mapa de referencia en tu Reproductor de documento. Esto le permite a la cadena de criterios que selecciona el Mapa y, a continuación, la Ubicación dentro de ella. Usted tiene que el código de un método en su clase de Jugador para manejar esto.

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

Así, de forma similar a cómo se respondió a sí mismo, excepto que usted todavía podría almacenar el location_id en su reproductor de documento en lugar de utilizar el coord attribs.

Otra forma sería poner Mapas, Ubicaciones, y los Jugadores en sus propias colecciones, en lugar de la integración de la Ubicación en el Mapa de la colección. Entonces usted podría usar de referencia de las relaciones sin hacer nada de lujo... sin embargo su realidad sólo el uso de una base de datos jerárquica que le gusta es una base de datos relacional en este punto...

11voto

bowsersenior Puntos 7841

Por FAVOR, vaya y VOTE por el "virtual colecciones" en MongoDB del issue tracker:

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

Es la 2ª característica más solicitada, pero todavía no ha sido prevista para el lanzamiento. Tal vez si suficiente gente a votar por ella y moverla a la número uno, la MongoDB team finalmente implementar.

6voto

Dan Healy Puntos 561

En mi caso, no es necesario que el objeto de referencia el documento incrustado. Desde el mongoid, grupo de usuario, he encontrado la solución: Utilizar referenced_in en el documento incrustado y NO se hace referencia en el exterior documento.

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

0voto

Scott Brown Puntos 124

Mi solución actual es hacer lo siguiente:

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

Esto funciona, pero se siente como un kluge.

0voto

Maedi Puntos 11

Pensar fuera de la caja, usted podría hacer la Ubicación de su propio documento y el uso de Mongoid Alize para generar automáticamente los datos incrustados en el documento de Mapa de Ubicación de los documentos.

https://github.com/dzello/mongoid_alize

La ventaja de este método es que puedes realizar consultas de forma eficiente cuando las condiciones son adecuadas, y más lento de referencia basado en las consultas sobre el documento original cuando no hay otra forma.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X