You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

search.rb 3.0KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. require 'sequel'
  2. require_relative './models/post'
  3. require_relative './models/thread'
  4. RESULTS_PER_PAGE = 50
  5. def search(params)
  6. query = params[:q].strip
  7. offset = (params[:page] - 1) * RESULTS_PER_PAGE
  8. username = params[:username].strip
  9. from_date = params[:from_date].strip
  10. to_date = params[:to_date].strip
  11. sort = params[:sort].strip
  12. exact_match = params[:exact_match].strip == "yes"
  13. errors = Array.new
  14. if from_date.empty?
  15. from_date = nil
  16. else
  17. if from_date.match(/\d{4}-\d{2}-\d{2}/)
  18. from_date = Date.parse(params[:from_date]) rescue errors << 'Invalid From Date'
  19. else
  20. errors << 'From Date must be in the format YYYY-MM-DD'
  21. end
  22. end
  23. if to_date.empty?
  24. to_date = nil
  25. else
  26. if to_date.match(/\d{4}-\d{2}-\d{2}/)
  27. to_date = Date.parse(params[:to_date]).next rescue errors << 'Invalid To Date'
  28. else
  29. errors << 'To Date must be in the format YYYY-MM-DD'
  30. end
  31. end
  32. if errors.empty? && !to_date.nil? && !from_date.nil? && to_date < from_date
  33. errors << 'To Date must be after From Date'
  34. end
  35. return {results: Array.new, errors: errors} unless errors.empty?
  36. results = case params[:type]
  37. when 'threads'
  38. search_threads(query, username, from_date, to_date, sort, offset, exact_match)
  39. when 'posts'
  40. search_posts(query, username, from_date, to_date, offset, exact_match)
  41. else
  42. Array.new
  43. end
  44. {results: results, errors: errors}
  45. end
  46. def search_threads(q, username, from_date, to_date, sort, offset, exact_match)
  47. sort = Sequel.desc(sort == 'post' ? :last_post_created_at : :created_at)
  48. query = VLV::Thread
  49. .select(Sequel.lit('threads.*, count(*) OVER() AS full_count'))
  50. .where(Sequel.lit("(LOWER(threads.creator) = LOWER(?) OR ? = '')", username, username))
  51. .where(Sequel.lit("created_at >= ? OR ? IS NULL", from_date, from_date))
  52. .where(Sequel.lit("created_at >= ? OR ? IS NULL", to_date, to_date))
  53. .order(sort)
  54. .limit(RESULTS_PER_PAGE)
  55. .offset(Sequel.lit('?', offset))
  56. if exact_match
  57. query.where(Sequel.ilike(:title, "%#{q}%"))
  58. else
  59. query.full_text_search(:title, Sequel.lit("websearch_to_tsquery(?)", q), tsquery: true, language: 'english')
  60. end
  61. end
  62. def search_posts(q, username, from_date, to_date, offset, exact_match)
  63. query = VLV::Post
  64. .select(Sequel.lit('posts.*, threads.title as thread_title, threads.remote_id as remote_thread_id, count(*) OVER() AS full_count'))
  65. .join(Sequel.lit('threads on posts.thread_id = threads.id'))
  66. .where(Sequel.lit("(LOWER(posts.creator) = LOWER(?) OR (? = ''))", username, username))
  67. .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", from_date, from_date))
  68. .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", to_date, to_date))
  69. .limit(RESULTS_PER_PAGE)
  70. .offset(Sequel.lit('?', offset))
  71. .order(Sequel.desc(Sequel.lit('posts.created_at')))
  72. if exact_match
  73. query.where(Sequel.ilike(:body, "%#{q}%"))
  74. else
  75. query.full_text_search(:tsv, Sequel.lit("websearch_to_tsquery(?)", q), {
  76. tsquery: true,
  77. tsvector: true,
  78. language: 'english'
  79. })
  80. end
  81. end