子关联的多个条件的活动记录查询
Active record query for multiple conditions on child association
我需要有关相关子查询的帮助。
一个项目有很多方面。 facet 的属性是 identifier
和 content
。 facet identifier
和 content
用于提供选项来过滤显示的项目 - 例如,identifier
可以是 'color' 而 content
'red' 或 identifier
是 'size' 而 content
是 '10`
我想要一个查询 return
所在的项目
(label contains a search term)
OR
( has a facet with an identifier equal to one of 2 given values AND the content includes the search term)
AND
(it ALSO has ANOTHER facet whose identifier is equal to one of a number of some different values AND content equal to one of a number of yet more different values).
我试过的 rails 查询
rails查询
items.joins(:facets)
.where('items.label LIKE ? OR facets.identifier LIKE ?', "%#{search_term}%", "%#{search_term}%")
.where('facets.identifier' => filter).where('facets.content' => value).uniq
转换为以下 sql 查询
SELECT DISTINCT (`items`.`id`) FROM `items` INNER JOIN `facets` ON
`facets`.`item_id` = `items`.`id` AND `facets`.`identifier` IN ('summary', 'description') AND
(items.label LIKE '%outing%' OR facets.content LIKE '%outing%') AND
`facets`.`identifier` = 'color' AND `facets`.`content` IN
('red')
这个return是一个空数组,因为我认为
之间存在冲突
`facets`.`identifier` IN ('summary', 'description')
和
`facets`.`identifier` = 'color'
如何编写一个查询,使 return 一个项目基于其多个方面。是否可以将其写为活动记录而不是原始 sql?
我确定了一种可行的方法,但不一定是最佳方法:
class ItemProvider
attr_reader :keyword, :filters
FACET_CONTENT_TO_SEARCH = %w[summary description]
def initialize(keyword, filters)
@keyword = keyword
@filters = filters
end
def retrieve
@items = Item.all
filter_by_keyword
filter_items
end
private
def filter_by_keyword
return @items if keyword.blank?
@items = @items
.joins(:facets)
.where('facets.identifier' => FACET_CONTENT_TO_SEARCH)
.where('items.label LIKE ? OR facets.content LIKE ?', "%#{keyword}%", "%#{keyword}%").uniq
end
def filter_items
return @items if filters.blank?
filters_to_hash.each do |filter, value|
@items = Item
.unscoped
.select("items.*")
.joins("INNER JOIN facets ON facets.facetable_id = items.id AND facets.facetable_type = 'Item'")
.where('facets.identifier' => filter)
.where('facets.content' => value)
end
end
def filters_to_hash
filters.reduce({}) do |acc, filter|
if acc[filter[:identifier]]
acc[filter[:identifier]] << filter[:value]
else
acc[filter[:identifier]] = [filter[:value]]
end
acc
end
end
end
我需要有关相关子查询的帮助。
一个项目有很多方面。 facet 的属性是 identifier
和 content
。 facet identifier
和 content
用于提供选项来过滤显示的项目 - 例如,identifier
可以是 'color' 而 content
'red' 或 identifier
是 'size' 而 content
是 '10`
我想要一个查询 return
所在的项目(label contains a search term)
OR
( has a facet with an identifier equal to one of 2 given values AND the content includes the search term)
AND
(it ALSO has ANOTHER facet whose identifier is equal to one of a number of some different values AND content equal to one of a number of yet more different values).
我试过的 rails 查询
rails查询
items.joins(:facets)
.where('items.label LIKE ? OR facets.identifier LIKE ?', "%#{search_term}%", "%#{search_term}%")
.where('facets.identifier' => filter).where('facets.content' => value).uniq
转换为以下 sql 查询
SELECT DISTINCT (`items`.`id`) FROM `items` INNER JOIN `facets` ON
`facets`.`item_id` = `items`.`id` AND `facets`.`identifier` IN ('summary', 'description') AND
(items.label LIKE '%outing%' OR facets.content LIKE '%outing%') AND
`facets`.`identifier` = 'color' AND `facets`.`content` IN
('red')
这个return是一个空数组,因为我认为
之间存在冲突`facets`.`identifier` IN ('summary', 'description')
和
`facets`.`identifier` = 'color'
如何编写一个查询,使 return 一个项目基于其多个方面。是否可以将其写为活动记录而不是原始 sql?
我确定了一种可行的方法,但不一定是最佳方法:
class ItemProvider
attr_reader :keyword, :filters
FACET_CONTENT_TO_SEARCH = %w[summary description]
def initialize(keyword, filters)
@keyword = keyword
@filters = filters
end
def retrieve
@items = Item.all
filter_by_keyword
filter_items
end
private
def filter_by_keyword
return @items if keyword.blank?
@items = @items
.joins(:facets)
.where('facets.identifier' => FACET_CONTENT_TO_SEARCH)
.where('items.label LIKE ? OR facets.content LIKE ?', "%#{keyword}%", "%#{keyword}%").uniq
end
def filter_items
return @items if filters.blank?
filters_to_hash.each do |filter, value|
@items = Item
.unscoped
.select("items.*")
.joins("INNER JOIN facets ON facets.facetable_id = items.id AND facets.facetable_type = 'Item'")
.where('facets.identifier' => filter)
.where('facets.content' => value)
end
end
def filters_to_hash
filters.reduce({}) do |acc, filter|
if acc[filter[:identifier]]
acc[filter[:identifier]] << filter[:value]
else
acc[filter[:identifier]] = [filter[:value]]
end
acc
end
end
end