From f45ce8684292d23490b36f7f841cc053ea6793bb Mon Sep 17 00:00:00 2001 From: Neetpone <132411956+Neetpone@users.noreply.github.com> Date: Sat, 13 Apr 2024 18:21:33 -0400 Subject: [PATCH] refactor: create story finder instead of doing all that junk inline --- app/controllers/search_controller.rb | 18 ++--------- app/lib/story_finder.rb | 45 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 app/lib/story_finder.rb diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 9247a12..27dcdff 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -2,7 +2,7 @@ # This whole class is a giant mess but I coded it fast so give me a break. class SearchController < ApplicationController ALLOWED_SORT_DIRS = %i[asc desc] - ALLOWED_SORT_FIELDS = %i[title author date_published date_updated num_words rel] + ALLOWED_SORT_FIELDS = %i[title author date_published date_updated num_words rating rel] before_action :load_tags @@ -28,13 +28,10 @@ class SearchController < ApplicationController # This was mainly written this way to match the way FiMFetch's query interface looks, without using JS. # I should do a Derpibooru-esque textual search system sometime. - @search = Story.fancy_search( + @search = StoryFinder.new(@search_params).find( per_page: @per_page, page: @page_num ) do |s| - s.add_query(match: { title: { query: @search_params[:q], operator: :and } }) if @search_params[:q].present? - s.add_query(match: { author: { query: @search_params[:author], operator: :and } }) if @search_params[:author].present? - # tags -> match any of the included tags, exclude any of the excluded tags tag_musts, tag_must_nots = parse_tag_queries boolses = {} @@ -48,17 +45,6 @@ class SearchController < ApplicationController ) if tag_must_nots.any? s.add_query(bool: boolses) if boolses.any? - - # ratings -> match stories with any of them - s.add_filter(bool: { - should: @search_params[:ratings].keys.map { |k| { term: { content_rating: k } } } - }) if @search_params[:ratings].present? - - # completeness -> match stories with any of them - s.add_filter(bool: { - should: @search_params[:state].keys.map { |k| { term: { completion_status: k } } } - }) if @search_params[:state].present? - # sort direction if using_random s.add_sort _random: :desc diff --git a/app/lib/story_finder.rb b/app/lib/story_finder.rb new file mode 100644 index 0000000..716d4bf --- /dev/null +++ b/app/lib/story_finder.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true +class StoryFinder + # key is the params scalar field, value is the ES document field to search on + QUERIES = { + q: :title, + author: :author + }.freeze + + # key is the params array field, value is the query type and the ES document field to search on. + FILTERS = { + ratings: { type: :should, field: :content_rating }, + state: { type: :should, field: :completion_status } + }.freeze + + def initialize(params) + @params = params + end + + def find(opts) + Story.fancy_search(opts) do |s| + build_queries(s) + build_filters(s) + + yield s if block_given? + end + end + + private + + # @param s FancySearchable::FancySearchableOptions + def build_queries(s) + QUERIES.each do |param, field| + s.add_query match: { field => { query: @params[param], operator: :and } } if @params[param].present? + end + end + + # @param s FancySearchable::FancySearchableOptions + def build_filters(s) + FILTERS.each do |param, opts| + s.add_filter(bool: { + opts[:type] => @params[param].keys.map { |k| { term: { opts[:field] => k } } } + }) if @params[param].present? + end + end +end