From 8f03b1cc47dc4cf7876d2862ac8308486f0d932a Mon Sep 17 00:00:00 2001 From: Julian Rother <julianr@fsmpi.rwth-aachen.de> Date: Sat, 20 Aug 2016 03:36:55 +0200 Subject: [PATCH] Implemented basic full-text search --- server.py | 32 +++++++++++++++++++++++++++++++- templates/base.html | 14 ++++++++------ templates/search.html | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 templates/search.html diff --git a/server.py b/server.py index 40bb331..68334c6 100755 --- a/server.py +++ b/server.py @@ -54,6 +54,23 @@ def query(operation, *params): cur.execute(operation, params) return cur.fetchall() +def searchquery(text, columns, match, tables, suffix, *suffixparams): + params = [] + subexprs = [] + words = text.split(' ') + prio = len(words)+1 + for word in words: + if word == '' or word.isspace(): + continue + matchexpr = ' OR '.join(['%s LIKE ?'%column for column in match]) + subexprs.append('SELECT %s, %s AS _prio FROM %s WHERE %s'%(columns, str(prio), tables, matchexpr)) + params += ['%'+word+'%']*len(match) + prio -= 1 + if subexprs == []: + return [] + expr = 'SELECT *,SUM(_prio) AS _score FROM (%s) AS _tmp %s'%(' UNION '.join(subexprs), suffix) + return query(expr, *params, *suffixparams) + @app.route('/') def index(): return render_template('index.html', latestvideos=query(''' @@ -83,7 +100,20 @@ def play(): lecture=query('SELECT * FROM lectures WHERE id = ?', id)[0], videos=query('SELECT * FROM videos WHERE lecture_id = ?', id)) else: - return redirect(url_for(index)) + return redirect(url_for('index')) + +@app.route('/search') +def search(): + if 'q' not in request.args: + return redirect(url_for('index')) + q = request.args['q'] + courses = searchquery(q, '*', ['title', 'short', 'organizer', 'subject', 'description'], + 'courses', 'WHERE (? OR (visible AND listed)) GROUP BY id ORDER BY _score DESC, semester DESC LIMIT 20', False) + lectures = searchquery(q, 'lectures.*, courses.visible AS coursevisible, courses.listed, courses.short, courses.downloadable, courses.title AS coursetitle', + ['lectures.title', 'lectures.comment', 'lectures.speaker', 'courses.short'], + 'lectures LEFT JOIN courses on (courses.id = lectures.course_id)', + 'WHERE (? OR (coursevisible AND listed AND visible)) GROUP BY id ORDER BY _score DESC, time DESC LIMIT 30', False) + return render_template('search.html', searchtext=request.args['q'], courses=courses, lectures=lectures) if __name__ == '__main__': app.run() diff --git a/templates/base.html b/templates/base.html index 6c1e6ad..82c8ed8 100644 --- a/templates/base.html +++ b/templates/base.html @@ -57,12 +57,14 @@ {% endfor %} </ul> </div> - <div class="col-xs-5"> - <span class=""><input class="form-control" type="text" placeholder="Search"> - </div> - <div class="col-md-1"> - <span class=""><button class="btn btn-default" type="submit">Submit</button> - </div> + <form action="search"> + <div class="col-xs-5"> + <span class=""><input class="form-control" type="text" name="q" placeholder="Search" value="{{ searchtext }}"> + </div> + <div class="col-md-1"> + <span class=""><button class="btn btn-default" type="submit">Submit</button> + </div> + </form> </div> <div class="row"> <div class="col-md-12"> diff --git a/templates/search.html b/templates/search.html new file mode 100644 index 0000000..e400678 --- /dev/null +++ b/templates/search.html @@ -0,0 +1,38 @@ +{% from 'macros.html' import preview %} +{% extends "base.html" %} +{% block content %} +<div class="container"> + <div class="panel panel-default"> + <div class="panel-heading"> + <h1>Veranstaltungen</h1> + </div> + <div class="panel-body"> + {% if courses == [] %} + Nichts gefunden! + {% else %} + <ul class="list-group courselist"> + {% for course in courses %} + <li class="list-group-item">{{ course['title'] }}</li> + {% endfor %} + </ul> + {% endif %} + </div> + </div> + <div class="panel panel-default"> + <div class="panel-heading"> + <h1>Videos</h1> + </div> + <div class="panel-body"> + {% if lectures == [] %} + Nichts gefunden! + {% else %} + <ul class="list-group videopreview"> + {% for lecture in lectures %} + {{ preview(lecture) }} + {% endfor %} + </ul> + {% endif %} + </div> + </div> +</div> +{% endblock %} -- GitLab