eBooru/app/logical/post_query_builder.rb

162 lines
5.8 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
class PostQueryBuilder
attr_accessor :query_string
def initialize(query_string)
@query_string = query_string
end
def add_tag_string_search_relation(tags, relation)
if tags[:must].any?
relation = relation.where("string_to_array(posts.tag_string, ' ') @> ARRAY[?]", tags[:must])
end
if tags[:must_not].any?
relation = relation.where("NOT(string_to_array(posts.tag_string, ' ') && ARRAY[?])", tags[:must_not])
end
if tags[:should].any?
relation = relation.where("string_to_array(posts.tag_string, ' ') && ARRAY[?]", tags[:should])
end
relation
end
def add_array_range_relation(relation, values, field)
values&.each do |value|
relation = relation.add_range_relation(value, field)
end
relation
end
def search
q = TagQuery.new(query_string)
relation = Post.all
relation = add_array_range_relation(relation, q[:post_id], "posts.id")
relation = add_array_range_relation(relation, q[:mpixels], "posts.image_width * posts.image_height / 1000000.0")
relation = add_array_range_relation(relation, q[:ratio], "ROUND(1.0 * posts.image_width / GREATEST(1, posts.image_height), 2)")
relation = add_array_range_relation(relation, q[:width], "posts.image_width")
relation = add_array_range_relation(relation, q[:height], "posts.image_height")
relation = add_array_range_relation(relation, q[:score], "posts.score")
relation = add_array_range_relation(relation, q[:fav_count], "posts.fav_count")
relation = add_array_range_relation(relation, q[:filesize], "posts.file_size")
relation = add_array_range_relation(relation, q[:change_seq], "posts.change_seq")
relation = add_array_range_relation(relation, q[:date], "posts.created_at")
relation = add_array_range_relation(relation, q[:age], "posts.created_at")
TagCategory::CATEGORIES.each do |category|
2023-12-03 09:36:37 -05:00
relation = add_array_range_relation(relation, q[:"#{category}_tag_count"], "posts.tag_count_#{category}")
end
relation = add_array_range_relation(relation, q[:post_tag_count], "posts.tag_count")
TagQuery::COUNT_METATAGS.each do |column|
relation = add_array_range_relation(relation, q[column.to_sym], "posts.#{column}")
end
if q[:md5]
relation = relation.where("posts.md5": q[:md5])
end
if q[:status] == "pending"
relation = relation.where("posts.is_pending = TRUE")
elsif q[:status] == "flagged"
relation = relation.where("posts.is_flagged = TRUE")
elsif q[:status] == "modqueue"
relation = relation.where("posts.is_pending = TRUE OR posts.is_flagged = TRUE")
elsif q[:status] == "deleted"
relation = relation.where("posts.is_deleted = TRUE")
elsif q[:status] == "active"
relation = relation.where("posts.is_pending = FALSE AND posts.is_deleted = FALSE AND posts.is_flagged = FALSE")
elsif q[:status] == "all" || q[:status] == "any"
# do nothing
elsif q[:status_must_not] == "pending"
relation = relation.where("posts.is_pending = FALSE")
elsif q[:status_must_not] == "flagged"
relation = relation.where("posts.is_flagged = FALSE")
elsif q[:status_must_not] == "modqueue"
relation = relation.where("posts.is_pending = FALSE AND posts.is_flagged = FALSE")
elsif q[:status_must_not] == "deleted"
relation = relation.where("posts.is_deleted = FALSE")
elsif q[:status_must_not] == "active"
relation = relation.where("posts.is_pending = TRUE OR posts.is_deleted = TRUE OR posts.is_flagged = TRUE")
end
q[:filetype]&.each do |filetype|
relation = relation.where("posts.file_ext": filetype)
end
q[:filetype_must_not]&.each do |filetype|
relation = relation.where.not("posts.file_ext": filetype)
end
if q[:pool] == "none"
relation = relation.where("posts.pool_string = ''")
elsif q[:pool] == "any"
relation = relation.where("posts.pool_string != ''")
end
q[:uploader_ids]&.each do |uploader_id|
relation = relation.where("posts.uploader_id": uploader_id)
end
q[:uploader_ids_must_not]&.each do |uploader_id|
relation = relation.where.not("posts.uploader_id": uploader_id)
end
if q[:approver] == "any"
relation = relation.where("posts.approver_id is not null")
elsif q[:approver] == "none"
relation = relation.where("posts.approver_id is null")
end
q[:approver_ids]&.each do |approver_id|
relation = relation.where("posts.approver_id": approver_id)
end
q[:approver_ids_must_not]&.each do |approver_id|
relation = relation.where.not("posts.approver_id": approver_id)
end
if q[:commenter] == "any"
relation = relation.where("posts.last_commented_at is not null")
elsif q[:commenter] == "none"
relation = relation.where("posts.last_commented_at is null")
end
if q[:noter] == "any"
relation = relation.where("posts.last_noted_at is not null")
elsif q[:noter] == "none"
relation = relation.where("posts.last_noted_at is null")
end
if q[:parent] == "none"
relation = relation.where("posts.parent_id IS NULL")
elsif q[:parent] == "any"
relation = relation.where("posts.parent_id IS NOT NULL")
end
q[:parent_ids]&.each do |parent_id|
relation = relation.where("posts.parent_id = ?", parent_id)
end
q[:parent_ids_must_not]&.each do |parent_id|
relation = relation.where.not("posts.parent_id = ?", parent_id)
end
if q[:child] == "none"
relation = relation.where("posts.has_children = FALSE")
elsif q[:child] == "any"
relation = relation.where("posts.has_children = TRUE")
end
q[:rating]&.each do |rating|
relation = relation.where("posts.rating = ?", rating)
end
q[:rating_must_not]&.each do |rating|
relation = relation.where("posts.rating = ?", rating)
end
add_tag_string_search_relation(q[:tags], relation)
end
end