123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- require 'sequel'
-
- require_relative './models/post'
- require_relative './models/thread'
-
- RESULTS_PER_PAGE = 50
-
- def search(params)
- query = params[:q].strip
- offset = (params[:page] - 1) * RESULTS_PER_PAGE
- username = params[:username].strip
- from_date = params[:from_date].strip
- to_date = params[:to_date].strip
- sort = (params[:sort] || "").strip
- exact_match = params[:exact_match].strip == "yes"
-
- errors = Array.new
-
- if from_date.empty?
- from_date = nil
- else
- if from_date.match(/\d{4}-\d{2}-\d{2}/)
- from_date = Date.parse(params[:from_date]) rescue errors << 'Invalid From Date'
- else
- errors << 'From Date must be in the format YYYY-MM-DD'
- end
- end
-
- if to_date.empty?
- to_date = nil
- else
- if to_date.match(/\d{4}-\d{2}-\d{2}/)
- to_date = Date.parse(params[:to_date]).next rescue errors << 'Invalid To Date'
- else
- errors << 'To Date must be in the format YYYY-MM-DD'
- end
- end
-
- if errors.empty? && !to_date.nil? && !from_date.nil? && to_date < from_date
- errors << 'To Date must be after From Date'
- end
-
- return {results: Array.new, errors: errors} unless errors.empty?
-
- results = case params[:type]
- when 'threads'
- search_threads(query, username, from_date, to_date, sort, offset, exact_match)
- when 'posts'
- search_posts(query, username, from_date, to_date, offset, exact_match)
- else
- Array.new
- end
-
- {results: results, errors: errors}
- end
-
- def search_threads(q, username, from_date, to_date, sort, offset, exact_match)
- sort = Sequel.desc(sort == 'post' ? :last_post_created_at : :created_at)
- query = VLV::Thread
- .select(Sequel.lit('threads.*'))
- .where(Sequel.lit("(LOWER(threads.creator) = LOWER(?) OR ? = '')", username, username))
- .where(Sequel.lit("created_at >= ? OR ? IS NULL", from_date, from_date))
- .where(Sequel.lit("created_at >= ? OR ? IS NULL", to_date, to_date))
- .order(sort)
- .limit(RESULTS_PER_PAGE)
- .offset(Sequel.lit('?', offset))
-
- count_query = VLV::Thread
- .select(Sequel.lit('count(*) as full_count'))
- .where(Sequel.lit("(LOWER(threads.creator) = LOWER(?) OR ? = '')", username, username))
- .where(Sequel.lit("created_at >= ? OR ? IS NULL", from_date, from_date))
- .where(Sequel.lit("created_at >= ? OR ? IS NULL", to_date, to_date))
-
- if exact_match
- filter = Sequel.ilike(:title, "%#{q}%")
- result = query.where(filter)
- full_count = count_query.where(filter).first.values[:full_count]
- [full_count, result]
- else
- result = query.full_text_search(:title, Sequel.lit("websearch_to_tsquery(?)", q), tsquery: true, language: 'english')
- full_count = count_query.full_text_search(
- :title, Sequel.lit("websearch_to_tsquery(?)", q), tsquery: true, language: 'english'
- ).first.values[:full_count]
- [full_count, result]
- end
- end
-
- def search_posts(q, username, from_date, to_date, offset, exact_match)
- query = VLV::Post
- .select(Sequel.lit('posts.*, threads.title as thread_title, threads.remote_id as remote_thread_id'))
- .join(Sequel.lit('threads on posts.thread_id = threads.id'))
- .where(Sequel.lit("(LOWER(posts.creator) = LOWER(?) OR (? = ''))", username, username))
- .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", from_date, from_date))
- .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", to_date, to_date))
- .limit(RESULTS_PER_PAGE)
- .offset(Sequel.lit('?', offset))
- .order(Sequel.desc(Sequel.lit('posts.created_at')))
-
- count_query = VLV::Post
- .select(Sequel.lit('count(*) as full_count'))
- .join(Sequel.lit('threads on posts.thread_id = threads.id'))
- .where(Sequel.lit("(LOWER(posts.creator) = LOWER(?) OR (? = ''))", username, username))
- .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", from_date, from_date))
- .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", to_date, to_date))
-
- if exact_match
- result = query.where(Sequel.ilike(:body, "%#{q}%"))
- full_count = count_query.where(Sequel.ilike(:body, "%#{q}%")).first.values[:full_count]
- [full_count, result]
- else
- result = query.full_text_search(:tsv, Sequel.lit("websearch_to_tsquery(?)", q), {
- tsquery: true,
- tsvector: true,
- language: 'english'
- })
- full_count = count_query.full_text_search(:tsv, Sequel.lit("websearch_to_tsquery(?)", q), {
- tsquery: true,
- tsvector: true,
- language: 'english'
- }).first.values[:full_count]
- [full_count, result]
- end
- end
|