Browse Source

Add exact match function

master
Dylan Baker 2 years ago
parent
commit
8bbc70cc5a
3 changed files with 57 additions and 46 deletions
  1. 41
    44
      lib/search.rb
  2. 1
    0
      web/server.rb
  3. 15
    2
      web/views/partials/search.erb

+ 41
- 44
lib/search.rb View File

@@ -1,5 +1,8 @@
1 1
 require 'sequel'
2 2
 
3
+require_relative './models/post'
4
+require_relative './models/thread'
5
+
3 6
 RESULTS_PER_PAGE = 50
4 7
 
5 8
 def search(params)
@@ -8,6 +11,8 @@ def search(params)
8 11
   username = params[:username].strip
9 12
   from_date = params[:from_date].strip
10 13
   to_date = params[:to_date].strip
14
+  sort = params[:sort].strip
15
+  exact_match = params[:exact_match].strip == "yes"
11 16
 
12 17
   errors = Array.new
13 18
 
@@ -39,18 +44,9 @@ def search(params)
39 44
 
40 45
   results = case params[:type]
41 46
   when 'threads'
42
-    sort =
43
-      case params[:sort]
44
-      when 'thread'
45
-        'created_at DESC'
46
-      when 'post'
47
-        'last_post_created_at DESC'
48
-      else
49
-        'created_at DESC'
50
-      end
51
-    search_threads(query, username, from_date, to_date, sort, offset)
47
+    search_threads(query, username, from_date, to_date, sort, offset, exact_match)
52 48
   when 'posts'
53
-    search_posts(query, username, from_date, to_date, offset)
49
+    search_posts(query, username, from_date, to_date, offset, exact_match)
54 50
   else
55 51
     Array.new
56 52
   end
@@ -58,39 +54,40 @@ def search(params)
58 54
   {results: results, errors: errors}
59 55
 end
60 56
 
61
-def search_threads(query, username, from_date, to_date, sort, offset)
62
-  DB[<<-SQL, query, username, username, from_date, from_date, to_date, to_date, offset]
63
-    SELECT
64
-      threads.*,
65
-      count(*) OVER() AS full_count
66
-    FROM threads
67
-    WHERE
68
-      to_tsvector(title) @@ plainto_tsquery(?)
69
-      AND (LOWER(threads.creator) = LOWER(?) OR ? = '')
70
-      AND (created_at >= ? OR ? IS NULL)
71
-      AND (created_at <= ? OR ? IS NULL)
72
-    ORDER BY #{sort}
73
-    LIMIT #{RESULTS_PER_PAGE}
74
-    OFFSET ?;
75
-  SQL
57
+def search_threads(q, username, from_date, to_date, sort, offset, exact_match)
58
+  sort = Sequel.desc(params[:sort] == 'post' ? :last_post_created_at : :created_at)
59
+  query = VLV::Thread
60
+    .select(Sequel.lit('threads.*, count(*) OVER() AS full_count'))
61
+    .where(Sequel.lit("(LOWER(threads.creator) = LOWER(?) OR ? = '')", username, username))
62
+    .where(Sequel.lit("created_at >= ? OR ? IS NULL", from_date, from_date))
63
+    .where(Sequel.lit("created_at >= ? OR ? IS NULL", to_date, to_date))
64
+    .order(sort)
65
+    .limit(RESULTS_PER_PAGE)
66
+    .offset(Sequel.lit('?', offset))
67
+
68
+  if exact_match
69
+    query.full_text_search(:title, q, phrase: true)
70
+  else
71
+    query.full_text_search(:title, Sequel.lit("websearch_to_tsquery(?)", q), tsquery: true)
72
+  end
76 73
 end
77 74
 
78
-def search_posts(query, username, from_date, to_date, offset)
79
-  DB[<<-SQL, query, username, username, from_date, from_date, to_date, to_date, offset]
80
-    SELECT
81
-      posts.*,
82
-      threads.title as thread_title,
83
-      threads.remote_id as remote_thread_id,
84
-      count(*) OVER() AS full_count
85
-    FROM posts
86
-    INNER JOIN threads on posts.thread_id = threads.id
87
-    WHERE
88
-      tsv @@ plainto_tsquery(?)
89
-      AND ((LOWER(posts.creator) = LOWER(?)) OR (? = ''))
90
-      AND (posts.created_at >= ? OR ? IS NULL)
91
-      AND (posts.created_at <= ? OR ? IS NULL)
92
-    ORDER BY posts.created_at DESC
93
-    LIMIT #{RESULTS_PER_PAGE}
94
-    OFFSET ?;
95
-  SQL
75
+def search_posts(q, username, from_date, to_date, offset, exact_match)
76
+  query = VLV::Post
77
+    .select(Sequel.lit('posts.*, threads.title as thread_title, threads.remote_id as remote_thread_id, count(*) OVER() AS full_count'))
78
+    .join(Sequel.lit('threads on posts.thread_id = threads.id'))
79
+    .where(Sequel.lit("(LOWER(posts.creator) = LOWER(?) OR (? = ''))", username, username))
80
+    .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", from_date, from_date))
81
+    .where(Sequel.lit("posts.created_at >= ? OR ? IS NULL", to_date, to_date))
82
+    .limit(RESULTS_PER_PAGE)
83
+    .offset(Sequel.lit('?', offset))
84
+
85
+  if exact_match
86
+    query.full_text_search(:body, q, phrase: true)
87
+  else
88
+    query.full_text_search(:tsv, Sequel.lit("websearch_to_tsquery(?)", q), {
89
+      tsquery: true,
90
+      tsvector: true
91
+    })
92
+  end
96 93
 end

+ 1
- 0
web/server.rb View File

@@ -37,6 +37,7 @@ class VLVSearch < Sinatra::Base
37 37
     params[:username] = String.new unless params[:username]
38 38
     params[:from_date] = String.new unless params[:from_date]
39 39
     params[:to_date] = String.new unless params[:to_date]
40
+    params[:exact_match] = String.new unless params[:exact_match]
40 41
 
41 42
     results = search(params)
42 43
 

+ 15
- 2
web/views/partials/search.erb View File

@@ -2,10 +2,21 @@
2 2
   <input name="q" type="search" value="<%= params[:q] %>" placeholder="Search for..." class="form__search" required>
3 3
   <div class="filters">
4 4
     <div class="filters__section">
5
+      <div class="filters__subsection">
6
+        <p>Exact match?</p>
7
+        <label class="form__label">
8
+          <input type="radio" name="exact_match" value="yes" <% if [nil,true, "yes"].include?(params[:exact_match]) %>checked<% end %>>
9
+          Yes
10
+        </label>
11
+        <label class="form__label">
12
+          <input type="radio" name="exact_match" value="no" <% if [false, "no"].include?(params[:exact_match]) %>checked<% end %>>
13
+          No
14
+        </label>
15
+      </div>
5 16
       <div class="filters__subsection">
6 17
         <p>Search in:</p>
7 18
         <label class="form__label">
8
-          <input type="radio" name="type" value="threads" <% if [nil, "threads"].include?(params[:type]) %>checked<% end%>>
19
+          <input type="radio" name="type" value="threads" <% if [nil, "threads"].include?(params[:type]) %>checked<% end %>>
9 20
           Threads
10 21
         </label>
11 22
         <label class="form__label">
@@ -13,6 +24,8 @@
13 24
           Posts
14 25
         </label>
15 26
       </div>
27
+    </div>
28
+    <div class="filters__section">
16 29
       <div class="filters__subsection">
17 30
         <p>From Date <em>(YYYY-MM-DD)</em>:</p>
18 31
         <label class="form__label">
@@ -48,7 +61,7 @@
48 61
       <div class="filters__subsection filters__subsection--sort <%= params[:type] == 'threads' ? 'open' : '' %>">
49 62
         <p>Sort by:</p>
50 63
         <label class="form__label">
51
-          <input type="radio" name="sort" value="thread" <% if [nil, "thread"].include? params[:sort] %>checked<% end%>>
64
+          <input type="radio" name="sort" value="thread" <% if [nil, "thread"].include? params[:sort] %>checked<% end %>>
52 65
           Thread creation
53 66
         </label>
54 67
         <label class="form__label">

Loading…
Cancel
Save