2010-01-03 13 views
4

J'essaie de comprendre comment mettre en page ma base de données pour un site sur lequel je travaille. Voici mes modèles:Quand utiliser les documents incorporés?

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 

je crois que le Like devrait être quelque part noyé, mais je vais avoir du mal à choisir une en raison de la fonctionnalité que je voudrais sortir.

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 

Bien que le problème vient lorsque vous utilisez un EmbeddedDocument, vous perdez la find, et d'autres méthodes utiles, et vous pouvez pas l'avoir embarqué dans les deux modèles. Donc, avoir seulement dans Item, je aurais besoin d'exécuter ce (mais ne peut pas):

item = Item.first 
item.likes.find_by_user_id(User.first._id) 

méthode non définie find_by_user_id sera lancé. Donc, si je devais incorporer cela dans mon User, je ne pouvais toujours pas faire cela.

likes = Like.all // will throw undefined `all` 

Alors je suis venu à la conclusing faire peut-être de cette façon:

class Like 
    include MongoMapper::Document 

    key :user_id, String, :required => true 
    key :item_id, String, :required => true 

    belongs_to :user 
    belongs_to :item 
end 

Mais cela semble que je suis en train de faire des choses encore à l'ancienne MySQL. Quelqu'un pourrait-il me donner un point sur la façon la plus probable de coder ceci avec MongoMapper?

Merci d'avance!

Répondre

9

S'il est possible de modéliser ceci dans MongoMapper, cela dépend si des données doivent être stockées dans le modèle Like. Si, comme dans votre exemple, il n'y a aucune donnée associée au modèle Like, il y a un moyen. La mise à jour la plus récente de MongoMapper a ajouté la prise en charge des relations plusieurs-à-plusieurs, même si elle en est encore à ses débuts.

Vous souhaitez créer vos modèles comme ceci:

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 

Ensuite, vous pouvez faire:

>> 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>] 

Malheureusement, ce que vous ne pouvez pas faire avec cette configuration est d'ajouter un comme de l'Item côté de la relation pour le moment. Cependant, il y a une question ouverte sur GitHub sur la création d'un revers approprié pour la relation many :in qui sera utilisé, en l'occurrence, comme suit:

many :fans, :class_name => "User", :source => :liked_items 

D'autre part, s'il y a des informations qui doivent être stockées dans le Like, comme la date à laquelle l'utilisateur a aimé l'élément, il n'y a pas moyen de le modéliser actuellement. L'installation idéale dans ce cas (sans tenir compte de ce qui est pris en charge dans MongoMapper en ce moment) serait similaire à ce que vous avez inclus dans votre question. Vous auriez besoin des trois modèles, avec Like intégré dans le modèle User et une relation has_many :through pour créer le lien de User à Item. Malheureusement, le support pour cela dans MongoMapper est probablement assez loin.

Si vous souhaitez encourager la prise en charge d'un comportement de ce type dans MongoMapper, vous pouvez poser des questions à ce sujet sur le mailing list ou ouvrir un numéro sur le MongoMapper github repository.

+0

Cela ne semble être la solution de fortune pour l'instant, je vais laisser cela courir quelques jours de plus pour voir si j'obtiens plus de réponses avant de choisir ceci comme réponse choisie! Merci! – Garrett

+0

Après un peu plus d'enquête, j'ai découvert que John a ouvert un problème sur GitHub pour un reverse inverse plus approprié de la relation 'many: in', donc ça arrive bientôt aussi. Cela n'aide pas si vous avez besoin d'enregistrer des informations dans le 'Like'. – Emily

+0

Les problèmes de MongoMapper ne sont plus suivis sur Github, mais ils utilisent Pivotal Tracker, ici: http://www.pivotaltracker.com/projects/33576 En fait, PivotalTracker est une application de gestion de projet Agile, non destinée au suivi des problèmes, donc Je pense que c'est un mauvais choix de la part des développeurs MongoMapper. –