]> git.ipfire.org Git - ipfire.org.git/commitdiff
wiki: Implement search
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 13 Nov 2018 00:11:55 +0000 (00:11 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 13 Nov 2018 00:11:55 +0000 (00:11 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/blog.py
src/backend/util.py
src/backend/wiki.py
src/templates/wiki/search-results.html [new file with mode: 0644]
src/web/wiki.py

index b6c8025c3462c09bdcce6e42afaea4577f491e7a..a7d2157161dda2512342cefe4ee7f313a05085c0 100644 (file)
@@ -259,7 +259,8 @@ templates_wiki_DATA = \
        src/templates/wiki/edit.html \
        src/templates/wiki/page.html \
        src/templates/wiki/recent-changes.html \
-       src/templates/wiki/revisions.html
+       src/templates/wiki/revisions.html \
+       src/templates/wiki/search-results.html
 
 templates_wikidir = $(templatesdir)/wiki
 
index 034fd4c1d5579697384460ebf04b8720aa7a8438..e9eac9f8d8b149015515688dd51e885813e6f104 100644 (file)
@@ -8,6 +8,7 @@ import textile
 import unicodedata
 
 from . import misc
+from . import util
 from .decorators import *
 
 # Used to automatically link some things
@@ -88,7 +89,7 @@ class Blog(misc.Object):
                        ORDER BY COALESCE(updated_at, created_at) DESC LIMIT %s", limit)
 
        def search(self, query, limit=None):
-               query = self._parse_search_query(query)
+               query = util.parse_search_query(query)
 
                return self._get_posts("SELECT blog.* FROM blog \
                        LEFT JOIN blog_search_index search_index ON blog.id = search_index.post_id \
@@ -96,25 +97,6 @@ class Blog(misc.Object):
                                ORDER BY ts_rank(search_index.document, to_tsquery('english', %s)) DESC \
                        LIMIT %s", query, query, limit)
 
-       def _parse_search_query(self, query):
-               q = []
-               for word in query.split():
-                       # Is this lexeme negated?
-                       negated = word.startswith("!")
-
-                       # Remove any special characters
-                       word = re.sub(r"\W+", "", word, flags=re.UNICODE)
-                       if not word:
-                               continue
-
-                       # Restore negation
-                       if negated:
-                               word = "!%s" % word
-
-                       q.append(word)
-
-               return " & ".join(q)
-
        def create_post(self, title, text, author, tags=[], lang="markdown"):
                """
                        Creates a new post and returns the resulting Post object
index ea7692a0dab3cb20210c9bb27e667da63d782c25..ff8248eaed4f1974308a48a3c79deaeef31efe90 100644 (file)
@@ -1,8 +1,28 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 import random
+import re
 import string
 
+def parse_search_query(query):
+       q = []
+       for word in query.split():
+               # Is this lexeme negated?
+               negated = word.startswith("!")
+
+               # Remove any special characters
+               word = re.sub(r"\W+", "", word, flags=re.UNICODE)
+               if not word:
+                       continue
+
+               # Restore negation
+               if negated:
+                       word = "!%s" % word
+
+               q.append(word)
+
+       return " & ".join(q)
+
 def format_size(s, max_unit=None):
        units = ("B", "kB", "MB", "GB", "TB")
 
index 651887a80b42f14ddb4985c74d64cf088621fb0a..50748e98b74b04c4d8dd8f362a9f4bee63fbac27 100644 (file)
@@ -5,6 +5,7 @@ import os.path
 import re
 
 from . import misc
+from . import util
 from .decorators import *
 
 class Wiki(misc.Object):
@@ -67,6 +68,23 @@ class Wiki(misc.Object):
 
                return ret
 
+       def search(self, query, limit=None):
+               query = util.parse_search_query(query)
+
+               res = self._get_pages("SELECT wiki.* FROM wiki_search_index search_index \
+                       LEFT JOIN wiki ON search_index.wiki_id = wiki.id \
+                       WHERE search_index.document @@ to_tsquery('english', %s) \
+                               ORDER BY ts_rank(search_index.document, to_tsquery('english', %s)) DESC \
+                       LIMIT %s", query, query, limit)
+
+               return list(res)
+
+       def refresh(self):
+               """
+                       Needs to be called after a page has been changed
+               """
+               self.db.execute("REFRESH MATERIALIZED VIEW wiki_search_index")
+
 
 class Page(misc.Object):
        def init(self, id, data=None):
diff --git a/src/templates/wiki/search-results.html b/src/templates/wiki/search-results.html
new file mode 100644 (file)
index 0000000..5e51473
--- /dev/null
@@ -0,0 +1,13 @@
+{% extends "../base.html" %}
+
+{% block title %}{{ _("Search results for '%s'") % q }}{% end block %}
+
+{% block content %}
+       <div class="card">
+               <div class="card-body">
+                       <h5>{{ _("Search results for '%s'") % q }}</h5>
+
+                       {% module WikiList(pages) %}
+               </div>
+       </div>
+{% end block %}
index 12aa9c0770a8b13a6c3b11cb0c8d4c6d3a7da8d3..a3d4e65bd67f7d211641fd41121680ed3c4b7e6d 100644 (file)
@@ -72,6 +72,10 @@ class PageHandler(auth.CacheMixin, base.BaseHandler):
                else:
                        self.redirect(page.url)
 
+               # Update the search index
+               with self.db.transaction():
+                       self.backend.wiki.refresh()
+
 
 class SearchHandler(auth.CacheMixin, base.BaseHandler):
        @base.blacklisted
@@ -79,8 +83,6 @@ class SearchHandler(auth.CacheMixin, base.BaseHandler):
                q = self.get_argument("q")
 
                pages = self.backend.wiki.search(q, limit=50)
-               if not pages:
-                       raise tornado.web.HTTPError(404, "Nothing found")
 
                self.render("wiki/search-results.html", q=q, pages=pages)