[英]How to select data records from join table with few options?
I'm writing a simple online shop on ruby and have a problem with items filtering.我正在用 ruby 编写一个简单的在线商店,但在项目过滤方面遇到了问题。 I'm trying to filter items by few options (eg 'color': 'red' and 'brand': 'zara').我正在尝试通过几个选项过滤项目(例如“颜色”:“红色”和“品牌”:“zara”)。
I expect to see only items that have both 'red' and 'zara' options.我希望只看到同时具有“红色”和“zara”选项的项目。
Everything is OK when I filter by one option.当我按一个选项过滤时,一切正常。 But with few options, it shows all items that have at least one of the options.但由于选项很少,它会显示至少具有其中一个选项的所有项目。
My filtering scope in Item model:我在项目模型中的过滤范围:
scope :by_options,
->(options) { joins(:items_options).where(items_options: { option_id: options }).distinct }
Items controller:物品控制器:
class ItemsController < ApplicationController
def index
@items = Item.all
filtering_params(params).each do |key, value|
@items = @items.public_send("by_#{key}", value) if value.present?
end
end
private
def filtering_params(params)
params.slice(:category, :options)
end
end
Generated query:生成的查询:
SELECT DISTINCT "items".* FROM "items" INNER JOIN "items_options" ON "items_options"."item_id" = "items"."id" WHERE "items_options"."option_id" IN (?, ?) [["option_id", 1], ["option_id", 6]]
I also tried to filter by options twice, but in this case @items are empty (6 and 1 are just examples, because I have item that have both of this options:我还尝试按选项过滤两次,但在这种情况下,@items 为空(6 和 1 只是示例,因为我的项目同时具有这两个选项:
@items = Item.by_options(6).by_options(1)
Generated query:生成的查询:
SELECT DISTINCT "items".* FROM "items" INNER JOIN "items_options" ON "items_options"."item_id" = "items"."id" WHERE "items_options"."option_id" = ? AND "items_options"."option_id" = ? [["option_id", 6], ["option_id", 1]]
DB schema:数据库架构:
create_table "items", force: :cascade do |t|
t.string "name", null: false
t.decimal "price", null: false
t.integer "available_count", null: false
t.integer "category_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["category_id"], name: "index_items_on_category_id"
end
create_table "items_options", id: false, force: :cascade do |t|
t.integer "item_id", null: false
t.integer "option_id", null: false
end
create_table "options", force: :cascade do |t|
t.string "name", null: false
t.integer "filter_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["filter_id"], name: "index_options_on_filter_id"
end
You can try:你可以试试:
scope :by_options,
->(options) {
self.joins(:items_options)
.having('SUM(items_options.option_id in (?)) = ?', options, options.size)
}
You're basically saying: "Give me all items that have all the items_options.option_id I specified".您基本上是在说:“给我所有具有我指定的所有 items_options.option_id 的项目”。
This is a little bit dirty, and I haven't tested it, but from the top of my head it should do the trick.这有点脏,我还没有测试过,但从我的头顶来看,它应该可以解决问题。
Otherwise, would you mind linking an SQL schema creation statement to your post so we could run the queries more easily?否则,您介意将 SQL 模式创建语句链接到您的帖子,以便我们可以更轻松地运行查询吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.