假设我有:具有has_many关联的项目:属性,那么我可以搜索所有具有名称'a_name'的属性和值'a_value'的项目
q: { properties_name_eq: 'a_name', properties_value_eq: 'a_value' }
现在,如果我想搜索具有名称为“a_name”且值为“a_value”的属性以及名称为“another_name”且值为“another_value”的属性的所有项目,该怎么办?
以下不起作用,因为它只加入属性表
q: {
g: {
'0' => { properties_name_eq: 'a_name', properties_value_eq: 'a_value' },
'1' => { properties_name_eq: 'another_name', properties_value_eq: 'another_value'}
}
}
生成的SQL看起来像这样
SELECT DISTINCT "items".* FROM "items"
LEFT OUTER JOIN "properties" ON "properties"."item_id" = "items"."id"
INNER JOIN ((SELECT "items".* FROM "items")) AS sel_111 on sel_111.id
WHERE
(("properties"."name" = 'a_name' AND "properties"."value" = 'a_value') AND ("properties"."name" = 'another_name' AND "properties"."value" = 'another_value'))
为了更清楚地了解我的目标,我将在下面粘贴一个规范。
Item.create name: 'ab', properties_attributes: [{ name: 'a', value: 'a1'}, {name: 'b', value: 'b1'}]
Item.create name: 'a', properties_attributes: [{ name: 'a', value: 'a1'}]
Item.create name: 'b', properties_attributes: [{name: 'b', value: 'b1'}]
Item.create name: 'ax', properties_attributes: [{ name: 'a', value: 'a1'}, {name: 'b', value: 'x'}]
Item.create name: 'bx', properties_attributes: [{ name: 'a', value: 'x'}, {name: 'b', value: 'b1'}]
Item.create name: 'other', properties_attributes: [{ name: 'other', value: '123'}]
get :index, q: { properties_name_eq: 'a', properties_value_eq: 'a1' }
names = JSON.parse(response.body).map{|u| u['name']}
expect(names).to match_array ['ab', 'a', 'ax'] # OK!
get :index,
q: {
m: 'or',
g: {
'0' => { properties_name_eq: 'a', properties_value_eq: 'a1' },
'1' => { properties_name_eq: 'b', properties_value_eq: 'b1'}
}
}
names = JSON.parse(response.body).map{|u| u['name']}
expect(names).to match_array ['ab'] #FAILS!
答案 0 :(得分:0)
使用Model.search(params[:q].try(:merge, m: 'or'))
,使用您的示例:
q: {
m: 'or',
g: {
'0' => { properties_name_eq: 'a_name', properties_value_eq: 'a_value' },
'1' => { properties_name_eq: 'another_name', properties_value_eq: 'another_value'}
}
}
您可以找到更多信息here
在查询的where级别需要or
,因为properties.name不能同时等于'a_name'和'another_name'。该表的第二个别名不是必需的。
答案 1 :(得分:0)
您可以使用多个查询来解决此问题。
item_ids
WHERE id IN (item_ids)
这是执行步骤1和步骤1的代码示例。 2:
def property_item_ids(conditions)
conditions.inject([]) do |result, (key, condition)|
result.method(result.empty? ? '+' : '&').(Property.ransack(m: "and", g: condition).pluck(:item_id).to_a)
end
end
获取具有所有属性的商品ID:
conditions = {
'0' => { properties_name_eq: 'a', properties_value_eq: 'a1' },
'1' => { properties_name_eq: 'b', properties_value_eq: 'b1'}
}
item_ids = property_item_ids(conditions)
对于第3步,使用item_ids
调用ransack:
q: {
m: 'and',
g: {
'0' => { item_id_in: item_ids }
}
}