From b655a7f88f653e143d85e1d01bfedde42dc6d9e4 Mon Sep 17 00:00:00 2001 From: Takeshi Umeda Date: Wed, 23 Sep 2020 23:01:54 +0900 Subject: [PATCH] Fix a slow query for TagFeed (#14861) * Fix a slow query for TagFeed * rename tags to tag_ids --- app/models/status.rb | 10 +++++----- app/models/tag_feed.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/models/status.rb b/app/models/status.rb index c6e16ff75..96d90e1c2 100644 --- a/app/models/status.rb +++ b/app/models/status.rb @@ -89,19 +89,19 @@ class Status < ApplicationRecord scope :without_replies, -> { where('statuses.reply = FALSE OR statuses.in_reply_to_account_id = statuses.account_id') } scope :without_reblogs, -> { where('statuses.reblog_of_id IS NULL') } scope :with_public_visibility, -> { where(visibility: :public) } - scope :tagged_with, ->(tag) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag }) } + scope :tagged_with, ->(tag_ids) { joins(:statuses_tags).where(statuses_tags: { tag_id: tag_ids }) } scope :in_chosen_languages, ->(account) { where(language: nil).or where(language: account.chosen_languages) } scope :excluding_silenced_accounts, -> { left_outer_joins(:account).where(accounts: { silenced_at: nil }) } scope :including_silenced_accounts, -> { left_outer_joins(:account).where.not(accounts: { silenced_at: nil }) } scope :not_excluded_by_account, ->(account) { where.not(account_id: account.excluded_from_timeline_account_ids) } scope :not_domain_blocked_by_account, ->(account) { account.excluded_from_timeline_domains.blank? ? left_outer_joins(:account) : left_outer_joins(:account).where('accounts.domain IS NULL OR accounts.domain NOT IN (?)', account.excluded_from_timeline_domains) } - scope :tagged_with_all, ->(tags) { - Array(tags).map(&:id).map(&:to_i).reduce(self) do |result, id| + scope :tagged_with_all, ->(tag_ids) { + Array(tag_ids).reduce(self) do |result, id| result.joins("INNER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}") end } - scope :tagged_with_none, ->(tags) { - Array(tags).map(&:id).map(&:to_i).reduce(self) do |result, id| + scope :tagged_with_none, ->(tag_ids) { + Array(tag_ids).reduce(self) do |result, id| result.joins("LEFT OUTER JOIN statuses_tags t#{id} ON t#{id}.status_id = statuses.id AND t#{id}.tag_id = #{id}") .where("t#{id}.tag_id IS NULL") end diff --git a/app/models/tag_feed.rb b/app/models/tag_feed.rb index 50634fe83..9a16ffc82 100644 --- a/app/models/tag_feed.rb +++ b/app/models/tag_feed.rb @@ -52,6 +52,6 @@ class TagFeed < PublicFeed end def tags_for(names) - Tag.matching_name(Array(names).take(LIMIT_PER_MODE)) if names.present? + Tag.matching_name(Array(names).take(LIMIT_PER_MODE)).pluck(:id) if names.present? end end