2012-05-24 3 views
2

I ont trois classesdocument incorporé Interrogation et tri dans MongoId

class Post 
include Mongoid::Document 
include Mongoid::Timestamps 
belongs_to :user, :inverse_of => nil 
embeds_many :comments, :as => :commentable 
field :content, :type => String 
end 

class Commment 
    include Mongoid::Document 
    include Mongoid::Timestamps 
    belongs_to :user, :inverse_of => nil 
    embedded_in :commentable, :polymoriphic => true 
end 

class User 
    has_many :posts, :dependent => :destroy 
    field :name, :type => String 
end 

Chaque fois que l'utilisateur crée un nouveau commentaire, je veux comparer le contenu de celui-ci avec le dernier commentaire que l'utilisateur a fait. Voici mon code qui va chercher le dernier commentaire par l'utilisateur:

comments_user=[] 
Post.where("comments.user_id" => user.id). 
    only(:comments). 
    each {|p| comments_user += p.comments.where(:user_id => user.id).to_a} 
latest_comment = comments_user.sort_by{|comment| comment[:updated_at]}.reverse.first 

Le code ci-dessus me donne le résultat mais l'approche adoptée est pas efficace que je dois parcourir à travers tous les postes que l'utilisateur a commmented trouver le dernier commentaire. Le cas échéant, quelqu'un peut-il me fournir une solution plus efficace à ce problème? En termes simples, n'y a-t-il pas moyen que je puisse obtenir tous les commentaires de cet utilisateur?

Répondre

3

Ceci est un problème standard avec l'intégration. Il améliore grandement certaines requêtes ("charger la publication avec tous ses commentaires"), mais rend les autres non-efficaces/impraticables ("trouver le dernier commentaire d'un utilisateur").

Je vois deux options:

  • Conserver l'intégration et les données en double. Autrement dit, lorsque l'utilisateur fait un commentaire, incorporez ce commentaire à un document de publication et au document de l'utilisateur. Cette duplication de données a ses inconvénients, bien sûr (que faire si vous avez besoin de modifier les commentaires?);

  • Arrêtez l'incorporation et commencez le référencement. Cela signifie que le commentaire est maintenant une entité de premier niveau. Vous ne pouvez pas charger rapidement un post avec des commentaires, car il n'y a pas de jointure. Mais les autres requêtes sont plus rapides maintenant, et il n'y a pas de duplication de données.

+0

Ok ... mais maintenant je ne veux pas modifier le modèle juste pour effectuer cette requête. N'y at-il aucune solution de contournement qui me donne le résultat? C'est bien si le résultat fonctionne pour la plupart des cas .. :) –

+1

ouais, ça marche mais c'est inefficace. Il recherche dans tous les messages que l'utilisateur a commentés. La solution n'est pas évolutive. Si possible, je veux quelque chose d'efficace et qui me donne la réponse dans la plupart des cas. –

+0

Il n'est pas possible d'effectuer une requête efficace avec votre schéma actuel. –

5

Cela devrait aller chercher la dernière User`s commentaire:

Post.where("comments.user_id" => user.id).order_by(:'comments.updated_at'.desc).limit(1).only(:comments).first 
+0

En fait, votre code me donne le dernier message. Je veux le dernier commentaire fait par l'utilisateur. Cela me donne le même résultat que le vôtre: Post.where ("comments.user_id" => user.id) .order_by (: updated_at.desc) .limit (1) .only (: comments) .first –

Questions connexes