J'essaie d'obtenir une liste de relations polymorphes sans avoir de doublons.
J'ai une table StoreViews avec un champ polymorphe appelé viewable (il y a donc une colonne viewable_id et viewable_type dans ma table). Maintenant, je veux afficher des vues avec chaque relation polymorphe apparaissant une seule fois, sans doublons.
@views = StoreView.
.distinct(:viewable_id)
.distinct(:viewable_type)
.order("created_at DESC")
.limit(10)
Ainsi, s'il existe deux enregistrements dans StoreViews, tous deux avec la même relation visible, @views ne doit renvoyer que le plus récent. Cependant, ce n'est pas le cas.
Les éléments ORDER BY
doivent apparaître dans la liste de sélection si SELECT DISTINCT
est spécifié. Il existe plusieurs façons de contourner ce problème .
Dans cet exemple, utiliser une fonction d'agrégat devrait fonctionner:
@views = StoreView
.select('DISTINCT viewable_type, viewable_id, MAX(created_at)')
.group(:viewable_type, :viewable_id)
.order('MAX(created_at) DESC')
.limit(10)
distinct
accepte uniquement un booléen en tant que paramètre permettant de spécifier si les enregistrements doivent être uniques ou non. Donc, distinct(:viewable_id)
est équivalent à distinct(true)
et ne fait pas ce que vous voulez. Au lieu d'utiliser distinct
, vous devez utiliser group
, qui renvoie un tableau avec des enregistrements distincts en fonction de l'attribut de groupe. Pour renvoyer le plus récent, à part la commande (avec order
) par created_at
, vous devez ajouter les champs dans group
:
@views = StoreView
.order(viewable_id: :desc, viewable_type: :desc, created_at: :desc)
.group(:viewable_id, :viewable_type)
Si vous avez besoin que les enregistrements retournés soient classés par created_at
, vous devez ajouter ceci.
ActiveRecord distinct:
https://apidock.com/Rails/ActiveRecord/QueryMethods/distinct
Spécifie si les enregistrements doivent être uniques ou non. Par exemple:
User.select(:name) # => Might return two records with the same name User.select(:name).distinct # => Returns 1 record per distinct name
Que dis-tu de ça:
@views = StoreView
.select(:viewable_id, :viewable_type)
.distinct
.order("created_at DESC")
.limit(10)
Vous pouvez aussi essayer
@views = StoreView
.select('DISTINCT `viewable_id`, `viewable_type`')
.order("created_at DESC")
.limit(10)