首页 > 解决方案 > Rails 和 SQL - 与数组、条目中的所有元素相关联

问题描述

我有这样的事情:

duplicates = ['a','b','c','d']

if duplicates.length > 4

     Photo.includes(:tags).where('tags.name IN (?)',duplicates)
     .references(:tags).limit(15).each do |f|
      
      returned_array.push(f.id)

    end

end

duplicatesPhoto是与其他标签重复的标签数组

我想要的是获得Photo包含重复数组中的所有标签的内容,但现在我得到的每一个都Photo包含数组中的至少一个标签。

感谢您的回答:

我尝试了它们,有些东西开始起作用,但对我来说不太清楚,需要一些时间来执行。

今天我让它创建数组,比较它们,获取数组中存在超过 X 次的重复项,最后获得唯一的照片 id 数组。

标签: sqlruby-on-railsrubyruby-on-rails-6

解决方案


如果您想查找具有所有给定标签的照片,您只需要应用 GROUP 并使用 HAVING 为组设置条件:

class Photo
  def self.with_tags(*names)
    t = Tag.arel_table
    joins(:tags)
      .where(tags: { name: names })
      .group(:id)
      .having(t[:id].count.eq(tags.length)) # COUNT(tags.id) = ?
  end
end

这有点像 WHERE 子句,但它适用于组。使用.gteq( >=) 代替.eq将为您提供可以包含列表中所有标签但可能有更多标签的记录。

解决这个问题的一个更好的方法是使用一个更好的域模型,它首先不允许重复:

class Photo < ApplicationRecord
  has_many :taggings
  has_many :tags, through: :taggings
end

class Tag < ApplicationRecord
  has_many :taggings
  has_many :photos, through: :taggings
  validates :name, 
    uniqueness: true,
    presenece: true
end

class Tagging < ApplicationRecord
  belongs_to :photo
  belongs_to :tag
  validates :tag_id, 
    uniqueness: { scope: :photo_id }
end

通过添加唯一索引tags.name和复合索引,taggings.tag_id无法taggings.photo_id创建重复项。


推荐阅读