關聯式資料庫對全文搜尋支援有限且不標準。本文採用純 Python 實作的 Whoosh 搜尋引擎,搭配 Flask-WhooshAlchemy 擴展,為微型部落格加入全文搜尋功能。
flask/bin/pip install Flask-WhooshAlchemy
在 config.py 指定索引儲存路徑:
WHOOSH_BASE = os.path.join(basedir, 'search.db')
在 models.py 的 Post 類別加入 __searchable__ 並初始化索引:
class Post(db.Model):
__searchable__ = ['body']
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<Post %r>' % self.body
import flask.ext.whooshalchemy as whooshalchemy
whooshalchemy.whoosh_index(app, Post)
現有資料需重建索引:刪除舊貼文並重新新增,或撰寫腳本重建。
>>> Post.query.whoosh_search('post').all()
[<Post 'my second post'>, <Post 'my first post'>, <Post 'my third and last post'>]
>>> Post.query.whoosh_search('second OR last').all()
[<Post 'my second post'>, <Post 'my third and last post'>]
Whoosh 支援布林運算子、欄位限定、通配符等豐富查詢語法。
MAX_SEARCH_RESULTS = 50
class SearchForm(Form):
search = TextField('search', validators=[Required()])
在 before_request 建立表單實例存入 g.search_form,base.html 導覽列內嵌表單:
<form action="{{ url_for('search') }}" method="post">
{{ g.search_form.hidden_tag() }}
{{ g.search_form.search(size=20) }}
<input type="submit" value="Search">
</form>
@app.route('/search', methods=['POST'])
@login_required
def search():
if not g.search_form.validate_on_submit():
return redirect(url_for('index'))
return redirect(url_for('search_results', query=g.search_form.search.data))
@app.route('/search_results/<query>')
@login_required
def search_results(query):
results = Post.query.whoosh_search(query, MAX_SEARCH_RESULTS).all()
return render_template('search_results.html', query=query, results=results)
採 POST-Redirect-GET 避免重新整理重複送出。結果頁面重複使用 post.html 子模板。
完成整合後,使用者即可在導覽列輸入關鍵字搜尋全站貼文內容。