我有以下型號:
class Fruit < ApplicationRecord
has_many :taggings, as: :tagable, dependent: :destroy
has_many :tags, through: :taggings
class Tagging < ApplicationRecord
belongs_to :tag
belongs_to :tagable, polymorphic: true
class Tag < ApplicationRecord
has_many :taggings, dependent: :destroy
has_many :fruits,
through: :taggings,
source: :tagable,
source_type: 'Fruit'
想象一下,我有帶有標簽“黃色”(ID:182)和“長”(ID:168)的水果“香蕉”。我需要一個查詢,它會給我帶有“黃色”和“長”標簽的水果。
香蕉確實有兩個標簽。
Fruit.find(97).tags
Fruit Load (4.1ms) SELECT "fruits".* FROM "fruits" WHERE "fruits"."id" = $1 ORDER BY name LIMIT $2 [["id", 97], ["LIMIT", 1]]
Tag Load (7.4ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."tagable_id" = $1 AND "taggings"."tagable_type" = $2 [["tagable_id", 97], ["tagable_type", "Fruit"]]
=> [#<標簽:0x000000010d50e9d0 id:168,名稱:“long”,created_at:星期三,2021 年 12 月 22 日 16:54:32.290923000 UTC 00:00,updated_at:星期三,2021 年 12 月 22 日 16:54:32.290923000 UTC 00:00>, #<Tag:0x000000010d50e868 id: 182, name: "yellow", created_at: 2022 年 4 月 18 日星期一 16:59:30.244851000 UTC 00:00, updated_at: 2022 年 4 月 18 日星期一 16:59:30.244851000世界標準時間 00:00>]
像這樣問:
irb(main):063:0> Fruit.joins(:tags).where(tags: { id: [168,182]}).to_sql
會得到我
"SELECT \"fruits\".* FROM \"fruits\" INNER JOIN \"taggings\" ON \"taggings\".\"tagable_type\" = 'Fruit' AND \"taggings\".\"tagable_id\" = \"fruits\".\"id\" INNER JOIN \"tags\" ON \"tags\".\"id\" = \"taggings\".\"tag_id\" WHERE \"tags\".\"id\" IN (168, 182) ORDER BY name"
這是所有帶有 tag.id 168 或 182 的水果。所以不行。
我試過了
Fruit.joins(:tags).where(tags: { id: 168 }).and(where(tags: { id: 182 }))
這將使我得到空的結果。
Fruit Load (2.0ms) SELECT "fruits".* FROM "fruits" INNER JOIN "taggings" ON "taggings"."tagable_type" = $1 AND "taggings"."tagable_id" = "fruits"."id" INNER JOIN "tags" ON "tags"."id" = "taggings"."tag_id" WHERE "tags"."id" = $2 AND "tags"."id" = $3 ORDER BY name [["tagable_type", "Fruit"], ["id", 168], ["id", 182]]
=> []
空的。
我也試過
f = Fruit.joins(:tags)
tags = [168,182]
tags.each do |tag|
f = f.where(tags: {id: tag})
end
Fruit Load (22.3ms) SELECT "fruits".* FROM "fruits" INNER JOIN "taggings" ON "taggings"."tagable_type" = $1 AND "taggings"."tagable_id" = "fruits"."id" INNER JOIN "tags" ON "tags"."id" = "taggings"."tag_id" WHERE "tags"."id" = $2 AND "tags"."id" = $3 ORDER BY name [["tagable_type", "Fruit"], ["id", 168], ["id", 182]]
再次,悲傷的故事,空洞的結果。
要求一個 tag.id 有效,一個或另一個也有效,但我找不到同時要求兩個標簽并獲得結果的方法。
謝謝
uj5u.com熱心網友回復:
作為 SQL GROUP BY,您需要什么,基本上選擇具有任一標簽的所有水果,然后按水果 id 對它們進行分組,并過濾??所有出現多次的水果。AFAIK 這不能用一個 SQL 查詢來完成,而是用兩個,這對于 ActiveRecord 可能會變得乏味。
用 Ruby 來完成大部分艱苦的作業怎么樣?
fruit = Fruit.joins(:tags).where(tags: { id: [168,182]}).to_a # returns the fruit that have both 2 tags
both_tags_ids = fruit.group_by { |f| f.id }.select { |fruit_id, arr|
arr.count > 1
}.values.flatten
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/464248.html
