Cuándo utilizar la inclusión de documentos?
-
22-09-2019 - |
Pregunta
Estoy tratando de encontrar la manera al formato para mi base de datos para un sitio que estoy trabajando. Aquí están mis modelos:
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
Creo que el Like
debe ser embebido en alguna parte, pero estoy teniendo un tiempo difícil elegir uno debido a la funcionalidad quisiera salir de ella.
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
A pesar de que el problema viene cuando se utiliza un EmbeddedDocument, se pierde la find
, y otros métodos de votos, y no se puede tenerlo incrustado en ambos modelos. Así que tener sólo en Item
, necesitaría para ejecutar este (pero no puede):
item = Item.first
item.likes.find_by_user_id(User.first._id)
será lanzada find_by_user_id
método no definido. Así que si yo estaba para insertar este en mi User
, todavía no podía hacerlo.
likes = Like.all // will throw undefined `all`
Así que llegó a la conclusing que tal vez hacerlo de esta manera:
class Like
include MongoMapper::Document
key :user_id, String, :required => true
key :item_id, String, :required => true
belongs_to :user
belongs_to :item
end
Sin embargo, esto parece como si todavía estoy tratando de hacer las cosas de la manera antigua de MySQL. ¿Podría alguien darme un punto de la forma más probable de este código con MongoMapper?
Gracias de antemano!
Solución
Si es posible modelar esto en MongoMapper depende de si hay datos que necesitan ser almacenados en el modelo Like
. Si, como en el ejemplo, no hay ningún dato asociado con el modelo Like
, hay una manera. La actualización más reciente a MongoMapper ha añadido soporte para las relaciones de muchos a muchos, a pesar de que todavía está en las primeras etapas.
Se crearía sus modelos como esto:
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
A continuación, puede hacer:
>> 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>]
Por desgracia, lo que no se puede hacer con esta configuración es añadir una como desde el lado de la relación Item
todavía. Sin embargo, hay un problema abierto en GitHub sobre la creación de un inverso correcto para la relación many :in
que será utilizado, en este caso, como sigue:
many :fans, :class_name => "User", :source => :liked_items
Por otro lado, si hay información que necesita ser almacenado en el Like
, tales como la fecha en que el usuario le gusta el artículo, no hay una manera de modelar la actualidad. La configuración ideal en este caso (sin tener en cuenta lo que está apoyada en MongoMapper en este momento) sería similar a lo que ha incluido en su pregunta. Se necesitaría los tres modelos, con Like
incrustado en el modelo User
y una relación has_many :through
para crear el enlace desde User
a Item
. Por desgracia, el apoyo para esto en MongoMapper es probablemente bastante lejos.
Si desea fomentar el apoyo para el comportamiento de este tipo en MongoMapper, y pregunta al respecto en la lista de correo o abrir un tema en la MongoMapper github repositorio .
Otros consejos
es posible que desee leer el documento "Insertar vs. Referencia" en la mongodb.org: http://www.mongodb.org/display/DOCS/Schema+Design#SchemaDesign-Embedvs.Reference