has_many:throughの追加スコープ条件

eeeeeean

ユーザーが1つ以上のタグを持つすべての投稿を見つけられるようにしたいと思います。また、タグを追加の基準にしたいので、たとえば、「ニュース」タグのみを含む投稿を検索したり、「ニュース」タグと「科学」タグの両方を含む投稿を検索したりできます。

現在私が持っていて機能しているのは、Postモデル、Tagモデル、およびMarkingと呼ばれる結合モデルです。投稿has_many :tags, through: :markingsタグIDの配列をPostクラスメソッドに渡すことで、必要なものを取得します。

post.rb

def self.from_tag_id_array array
  post_array = []
  Marking.where(tag_id: array).group_by(&:post_id).each do |p_id,m_array|
    post_array << p_id if m_array.map(&:tag_id).sort & array.sort == array.sort
  end
  where id: post_array
end

これはそこにたどり着くための不格好な方法のようです。アソシエーションなどのスコープでこれを行う方法はありますか?

クリス・ザルツバーグ

したがって、これらの種類のクエリを作成する際の一般的な経験則は、「Ruby-land」での作業を最小化し、「Database-land」での作業を最大化することです。上記のソリューションでは、セット内の任意のタグを使用してマーキングのセットをフェッチしています。arrayこれはおそらく非常に大きなセットになります(これらのタグのいずれかを持つすべての投稿)。これはruby配列で表され、処理されます(group_byRuby-worldにgroupあり、Database-landに相当します)。

そのため、読みにくいことを除けば、そのソリューションは、マーキングの大規模なセットに対しては遅くなります。

Rubyの世界で手間のかかる作業を行わずに問題を解決するには、いくつかの方法があります。1つの方法は、次のようなサブクエリを使用することです。

scope :with_tag_ids, ->(tag_ids) {
  tag_ids.map { |tag_id|
    joins(:markings).where(markings: { tag_id: tag_id })
  }.reduce(all) { |scope, subquery| scope.where(id: subquery) }
}

これにより、次のようなクエリが生成されます(ここでも、tag_ids 5および8に対して)

SELECT "posts".*
FROM "posts"
WHERE "posts"."id" IN (SELECT "posts"."id" FROM "posts" INNER JOIN "markings" ON "markings"."post_id" = "posts"."id" WHERE "markings"."tag_id" = 5)
  AND "posts"."id" IN (SELECT "posts"."id" FROM "posts" INNER JOIN "markings" ON "markings"."post_id" = "posts"."id" WHERE "markings"."tag_id" = 8)

ここではすべてがSQLで直接計算されるため、Rubyでは配列が生成または処理されないことに注意してください。これは通常、はるかに優れたスケーリングになります。

または、COUNTサブクエリなしで単一のクエリを使用して実行することもできます

scope :with_tag_ids, ->(tag_ids) {
  joins(:markings).where(markings: { tag_id: tag_ids }).
  group(:post_id).having('COUNT(posts.id) = ?', tag_ids.count)
}

これは次のようなSQLを生成します:

SELECT "posts".*
FROM "posts"
INNER JOIN "markings" ON "markings"."post_id" = "posts"."id"
WHERE "markings"."tag_id" IN (5, 8)
GROUP BY "post_id"
HAVING (COUNT(posts.id) = 2)

これは、あなたが同じのペアで複数のマーキングを持っていないことを前提とtag_idしてpost_id、カウントをオフに投げるだろう。

最後のソリューションがおそらく最も効率的だと思いますが、さまざまなソリューションを試して、データに最適なソリューションを確認する必要があります。

参照:activerecordとの交差点のクエリ

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

ActiveRecord、Rails 4:has_many:スコープ条件の失敗によるスルー

分類Dev

follower_idのrailsスコープ(has_manyからsource)

分類Dev

has_manyの後のhas_many:through?

分類Dev

has_manyのフォーム:through

分類Dev

has_manyのN + 1:through

分類Dev

スコープがSTIで非常に遅いhas_many

分類Dev

has_many:through Association

分類Dev

has_manyアソシエーションの合計に基づくRailsスコープ

分類Dev

Railsのhas_many関係でデフォルトでスコープを使用する

分類Dev

has_many関連要素のないRailsスコープフィルタリング要素

分類Dev

Rails5のhas_manyスコープ内で自分自身を参照しようとしています

分類Dev

Rails:モデルのhas_manyブロック内でスコープを使用する方法

分類Dev

has_manyアソシエーションによるRailsスコープ

分類Dev

Railsスコープはhas_many関係を「上」に移動します

分類Dev

Ruby on Rails'has_many:through '、データの保存

分類Dev

has_manyの逆クエリ:through

分類Dev

has_many through&CollectionSelectの問題

分類Dev

Rails、ActiveRecord、has_many:through:関連付けがないすべてのレコードを検索します

分類Dev

form_forを使用して複数のhas_many:throughレコードを作成する

分類Dev

has_many:throughアソシエーションのデフォルトスコープをオーバーライドするにはどうすればよいですか?

分類Dev

Ecto has_many:through in form

分類Dev

Finding Users with has_many :through

分類Dev

Ruby on Rails has_many:through in a polymorphicassociation

分類Dev

Rails has_many through Association Issue

分類Dev

2ステップのhas_many関係からすべてのレコードを1つのライナーで返す

分類Dev

has_manyリレーションのスコープから単一の値をどのように返しますか?

分類Dev

has_many:モデル名、コントローラー、属性のベストプラクティスを通じて?

分類Dev

Rails 4:ショーページでhas_many / belongs_to関係をスコープする

分類Dev

ActiveRecordのスコープ付きhas_manyでネストされた作成が失敗するのを防ぐ方法は?

Related 関連記事

  1. 1

    ActiveRecord、Rails 4:has_many:スコープ条件の失敗によるスルー

  2. 2

    follower_idのrailsスコープ(has_manyからsource)

  3. 3

    has_manyの後のhas_many:through?

  4. 4

    has_manyのフォーム:through

  5. 5

    has_manyのN + 1:through

  6. 6

    スコープがSTIで非常に遅いhas_many

  7. 7

    has_many:through Association

  8. 8

    has_manyアソシエーションの合計に基づくRailsスコープ

  9. 9

    Railsのhas_many関係でデフォルトでスコープを使用する

  10. 10

    has_many関連要素のないRailsスコープフィルタリング要素

  11. 11

    Rails5のhas_manyスコープ内で自分自身を参照しようとしています

  12. 12

    Rails:モデルのhas_manyブロック内でスコープを使用する方法

  13. 13

    has_manyアソシエーションによるRailsスコープ

  14. 14

    Railsスコープはhas_many関係を「上」に移動します

  15. 15

    Ruby on Rails'has_many:through '、データの保存

  16. 16

    has_manyの逆クエリ:through

  17. 17

    has_many through&CollectionSelectの問題

  18. 18

    Rails、ActiveRecord、has_many:through:関連付けがないすべてのレコードを検索します

  19. 19

    form_forを使用して複数のhas_many:throughレコードを作成する

  20. 20

    has_many:throughアソシエーションのデフォルトスコープをオーバーライドするにはどうすればよいですか?

  21. 21

    Ecto has_many:through in form

  22. 22

    Finding Users with has_many :through

  23. 23

    Ruby on Rails has_many:through in a polymorphicassociation

  24. 24

    Rails has_many through Association Issue

  25. 25

    2ステップのhas_many関係からすべてのレコードを1つのライナーで返す

  26. 26

    has_manyリレーションのスコープから単一の値をどのように返しますか?

  27. 27

    has_many:モデル名、コントローラー、属性のベストプラクティスを通じて?

  28. 28

    Rails 4:ショーページでhas_many / belongs_to関係をスコープする

  29. 29

    ActiveRecordのスコープ付きhas_manyでネストされた作成が失敗するのを防ぐ方法は?

ホットタグ

アーカイブ