0

У меня проблема с фильтрацией продуктов точными тегами, так как мой текущий запрос не возвращает точных совпадений, и я не могу получить правильные условия запроса.Rails multiple join условия запрос для точных тегов с имеет много сквозных связей

Пример

Area = ["small","big"], Surface = ["smooth","rough"]

Продукт А имеет только ["small","smooth","rough"], как теги

Если я фильтровать продукты с использованием ["small","big","smooth","rough"] как теги, я получаю продукт А в результатах поиска, но в идеале, он не должен возвращать результаты поиска.

У меня есть три модели, Product, Area и Surface. Area & Surface связаны с Product отношениями has_many through.

class Product < ActiveRecord::Base 
    has_many :product_areas 
    has_many :areas, :through => :product_areas 
    has_many :product_surfaces 
    has_many :surfaces, :through => :product_surfaces 

class Area < ActiveRecord::Base 
    #Surface model looks exactly the same as Area model 
    has_many :product_areas,dependent: :destroy 
    has_many :products, :through => :product_areas 

Мой запрос

area_ids = params[:area_ids] 
surface_ids = params[:surface_ids] 
@products = Product.where(nil) 
@products = @products.joins(:areas).where('areas.id' => area_ids).group('products.id').having("count(areas.id) >= ?",area_ids.count) unless area_ids.blank? 
@products = @products.joins(:surfaces).where('surfaces.id' => surface_ids).group('products.id').having("count(surfaces.id) >= ?",surface_ids.count) unless surface_ids.blank? 

ответ

0

Я решил эту проблему только сейчас с этим решением.

Сначала я использовал имена моделей для Area & Surface как их уникальных идентификтор, поскольку они могут быть противоречивыми ids и добавил их в массив.

Далее я зациклился на продуктах и ​​создал массив идентификаторов имен и сравнил два массива, чтобы проверить, пересекаются ли они. Пересечение будет означать, что фильтры поиска были правильными, и мы добавляем идентификатор продукта в третий массив, который хранит все product_ids перед выполнением запроса, чтобы получить продукты с этими идентификаторами продуктов.

@area = Area.all 
area_ids = params[:area_ids] 
@uniq_names = @area.where(id: area_ids).collect { |m| m.name } 
@products.each do |product| 
    @names = product.areas.map { |m| m.name } 
    # if intersect, then we add them to filtered product 
    if (@uniq_names - @names).empty? 
     product_ids << product.id 
    end 
end 
@products = Product.where(id: product_ids)