PERF: Use mini_sql for the query
On sites with many flages, it could take quite a long time for ActiveRecord to return all the joined data. It's now 3 queries instead of one, but significantly faster, especially if you have a minimum threshold set.
This commit is contained in:
parent
afbdf9c2d2
commit
71460fc203
|
@ -202,52 +202,61 @@ module FlagQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.flagged_topics
|
def self.flagged_topics
|
||||||
|
results = DB.query(<<~SQL)
|
||||||
results = PostAction
|
SELECT pa.post_action_type_id,
|
||||||
.flags
|
pa.post_id,
|
||||||
.active
|
p.topic_id,
|
||||||
.includes(post: [{ user: :user_stat }, :topic])
|
pa.created_at AS last_flag_at,
|
||||||
.references(:post)
|
p.user_id
|
||||||
.where("posts.user_id > 0")
|
FROM post_actions AS pa
|
||||||
.order('post_actions.created_at DESC')
|
INNER JOIN posts AS p ON pa.post_id = p.id
|
||||||
|
INNER JOIN topics AS t ON t.id = p.topic_id
|
||||||
|
WHERE pa.post_action_type_id IN (#{PostActionType.notify_flag_type_ids.join(',')})
|
||||||
|
AND pa.disagreed_at IS NULL
|
||||||
|
AND pa.deferred_at IS NULL
|
||||||
|
AND pa.agreed_at IS NULL
|
||||||
|
AND pa.deleted_at IS NULL
|
||||||
|
AND p.user_id > 0
|
||||||
|
AND p.deleted_at IS NULL
|
||||||
|
AND t.deleted_at IS NULL
|
||||||
|
ORDER BY pa.created_at DESC
|
||||||
|
SQL
|
||||||
|
|
||||||
ft_by_id = {}
|
ft_by_id = {}
|
||||||
users_by_id = {}
|
|
||||||
topics_by_id = {}
|
|
||||||
counts_by_post = {}
|
counts_by_post = {}
|
||||||
|
user_ids = Set.new
|
||||||
|
|
||||||
results.each do |pa|
|
results.each do |pa|
|
||||||
if pa.post.present? && pa.post.topic.present?
|
|
||||||
topic_id = pa.post.topic.id
|
|
||||||
|
|
||||||
ft = ft_by_id[topic_id] ||= OpenStruct.new(
|
ft = ft_by_id[pa.topic_id] ||= OpenStruct.new(
|
||||||
topic: pa.post.topic,
|
topic_id: pa.topic_id,
|
||||||
flag_counts: {},
|
flag_counts: {},
|
||||||
user_ids: [],
|
user_ids: Set.new,
|
||||||
last_flag_at: pa.created_at,
|
last_flag_at: pa.last_flag_at,
|
||||||
meets_minimum: false
|
meets_minimum: false
|
||||||
)
|
)
|
||||||
|
|
||||||
counts_by_post[pa.post.id] ||= 0
|
counts_by_post[pa.post_id] ||= 0
|
||||||
sum = counts_by_post[pa.post.id] += 1
|
sum = counts_by_post[pa.post_id] += 1
|
||||||
ft.meets_minimum = true if sum >= SiteSetting.min_flags_staff_visibility
|
ft.meets_minimum = true if sum >= SiteSetting.min_flags_staff_visibility
|
||||||
|
|
||||||
topics_by_id[topic_id] = pa.post.topic
|
ft.flag_counts[pa.post_action_type_id] ||= 0
|
||||||
ft.flag_counts[pa.post_action_type_id] ||= 0
|
ft.flag_counts[pa.post_action_type_id] += 1
|
||||||
ft.flag_counts[pa.post_action_type_id] += 1
|
|
||||||
|
|
||||||
ft.user_ids << pa.post.user_id
|
ft.user_ids << pa.user_id
|
||||||
ft.user_ids.uniq!
|
user_ids << pa.user_id
|
||||||
|
|
||||||
users_by_id[pa.post.user_id] ||= pa.post.user
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
all_topics = Topic.where(id: ft_by_id.keys).to_a
|
||||||
|
all_topics.each { |t| ft_by_id[t.id].topic = t }
|
||||||
|
|
||||||
flagged_topics = ft_by_id.values.select { |ft| ft.meets_minimum }
|
flagged_topics = ft_by_id.values.select { |ft| ft.meets_minimum }
|
||||||
|
Topic.preload_custom_fields(all_topics, TopicList.preloaded_custom_fields)
|
||||||
|
|
||||||
Topic.preload_custom_fields(topics_by_id.values, TopicList.preloaded_custom_fields)
|
{
|
||||||
|
flagged_topics: flagged_topics,
|
||||||
{ flagged_topics: flagged_topics, users: users_by_id.values }
|
users: User.where(id: user_ids)
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
Loading…
Reference in New Issue