Rails Arel sélectionnant des colonnes distinctes
J'ai atteint une légère bloc avec la nouvelle scope
méthodes (Arel 0.4.0, Rails 3.0.0.rc)
Fondamentalement, je dois:
Un topics
modèle, qui has_many :comments
et un comments
modèle (avec un topic_id
colonne) qui belongs_to :topics
.
Je suis en train de récupérer une collection de "Sujets Chauds", c'est à dire les sujets qui ont été récemment l'objet de commentaires. Actuel code est comme suit:
# models/comment.rb
scope :recent, order("comments.created_at DESC")
# models/topic.rb
scope :hot, joins(:comments) & Comment.recent & limit(5)
Si j'exécute Topic.hot.to_sql
la requête suivante est déclenché:
SELECT "topics".* FROM "topics" INNER JOIN "comments"
ON "comments"."topic_id" = "topics"."id"
ORDER BY comments.created_at DESC LIMIT 5
Cela fonctionne bien, mais il potentiellement renvoie les rubriques en double - Si le sujet n ° 3 a récemment été souligné plusieurs fois, il serait retourné plusieurs fois.
Ma question
Comment puis-je retourner un ensemble distinct de sujets, en gardant à l'esprit que j'ai encore besoin d'accéder à la comments.created_at
le terrain, de montrer de quoi il y a longtemps que le dernier post a été? J'imagine que quelque chose le long des lignes de distinct
ou group_by
mais je ne suis pas trop sûr de la meilleure façon d'aller à ce sujet.
Tous les conseils /suggestions sont appréciés - j'ai ajouté un 100 rep bounty dans l'espoir d'en arriver à une solution élégante bientôt.
source d'informationauteur Jeriko
Vous devez vous connecter pour publier un commentaire.
Solution 1
Ce n'utilise pas Arel, mais Rails 2.x syntaxe:
Assurez-vous de l'indice de la
created_at
ettopic_id
colonne dans lacomments
table.Solution 2
Ajouter un
last_comment_id
colonne dans votreTopic
modèle. Mise à jour lelast_comment_id
après la création d'un commentaire. Cette approche est beaucoup plus rapide que d'utiliser SQL complexe pour déterminer le dernier commentaire.E. g:
C'est beaucoup plus efficace que l'exploitation d'un complexe de requête SQL afin de déterminer les sujets chauds de l'.
Ce qui n'est pas élégant dans la plupart des implémentations de SQL. Une façon est d'abord d'obtenir la liste des cinq plus récentes observations regroupées par topic_id. Alors d'obtenir les commentaires.created_at par sous la sélection avec la clause IN.
Je suis très nouveau pour Arel, mais quelque chose comme cela pourrait fonctionner
Pour ce faire, vous devez avoir une portée avec un
GROUP BY
pour obtenir les dernières commentaire pour chaque sujet. Vous pouvez ensuite commander ce champ d'application encreated_at
d'obtenir la plus récente a commenté sur des sujets.Les ouvrages suivants, pour moi, en utilisant sqlite
J'ai utilisé les graines suivantes.rb pour générer les données de test
Et les suivants sont les résultats du test
Le SQL généré pour sqlite(restructuré) est extrêmement simple et je l'espère Arel rendrait différents SQL pour les autres moteurs, comme ce serait certainement un échec dans de nombreux moteurs de base de données que les colonnes à l'intérieur de Sujet ne sont pas dans la "liste Group by". Si cela présente un problème, alors vous pourriez probablement surmonter en limitant les colonnes sélectionnées pour juste les commentaires.topic_id
Puisque la question était de savoir Arel, je pensais que je voudrais ajouter ceci dans le, depuis des Rails 3.2.1 ajoute
uniq
à la QueryMethods:Si vous ajoutez
.uniq
à l'Arel il ajouteDISTINCT
à laselect
déclaration.par exemple
Topic.hot.uniq
Travaille également dans le champ d'application:
par exemple
scope :hot, joins(:comments).order("comments.created_at DESC").limit(5).uniq
Donc, je suppose que
devrait aussi probablement de travail.
Voir http://apidock.com/rails/ActiveRecord/QueryMethods/uniq