Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/honmaple/flask-msearch

Full text search for flask.
https://github.com/honmaple/flask-msearch

flask search sqlalchemy whoosh

Last synced: 3 months ago
JSON representation

Full text search for flask.

Lists

README

        

* flask-msearch
[[https://pypi.python.org/pypi/Flask-Msearch][https://img.shields.io/badge/pypi-v0.2.9.4-brightgreen.svg]]
[[https://python.org][https://img.shields.io/badge/python-2/3-brightgreen.svg]]
[[LICENSE][https://img.shields.io/badge/license-BSD-blue.svg]]

** Installation
To install flask-msearch:

#+BEGIN_SRC shell
pip install flask-msearch
# when MSEARCH_BACKEND = "whoosh"
pip install whoosh blinker
# when MSEARCH_BACKEND = "elasticsearch", only for 6.x.x
pip install elasticsearch==6.3.1
#+END_SRC

Or alternatively, you can download the repository and install manually by doing:
#+BEGIN_SRC sehll
git clone https://github.com/honmaple/flask-msearch
cd flask-msearch
python setup.py install
#+END_SRC

** Quickstart
#+BEGIN_SRC python
from flask_msearch import Search
[...]
search = Search()
search.init_app(app)

# models.py
class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['title', 'content']

# views.py
@app.route("/search")
def w_search():
keyword = request.args.get('keyword')
results = Post.query.msearch(keyword,fields=['title'],limit=20).filter(...)
# or
results = Post.query.filter(...).msearch(keyword,fields=['title'],limit=20).filter(...)
# elasticsearch
keyword = "title:book AND content:read"
# more syntax please visit https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
results = Post.query.msearch(keyword,limit=20).filter(...)
return ''
#+END_SRC

** Config

#+BEGIN_SRC python
# when backend is elasticsearch, MSEARCH_INDEX_NAME is unused
# flask-msearch will use table name as elasticsearch index name unless set __msearch_index__
MSEARCH_INDEX_NAME = 'msearch'
# simple,whoosh,elaticsearch, default is simple
MSEARCH_BACKEND = 'whoosh'
# table's primary key if you don't like to use id, or set __msearch_primary_key__ for special model
MSEARCH_PRIMARY_KEY = 'id'
# auto create or update index
MSEARCH_ENABLE = True
# logger level, default is logging.WARNING
MSEARCH_LOGGER = logging.DEBUG
# SQLALCHEMY_TRACK_MODIFICATIONS must be set to True when msearch auto index is enabled
SQLALCHEMY_TRACK_MODIFICATIONS = True
# when backend is elasticsearch
ELASTICSEARCH = {"hosts": ["127.0.0.1:9200"]}
#+END_SRC

** Usage
#+BEGIN_SRC python
from flask_msearch import Search
[...]
search = Search()
search.init_app(app)

class Post(db.Model):
__tablename__ = 'basic_posts'
__searchable__ = ['title', 'content']

id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(49))
content = db.Column(db.Text)

def __repr__(self):
return ''.format(self.title)
#+END_SRC

if raise *sqlalchemy ValueError*,please pass db param to Search
#+BEGIN_SRC python
db = SQLalchemy()
search = Search(db=db)
#+END_SRC

*** Create_index
#+BEGIN_SRC sh
search.create_index()
search.create_index(Post)
#+END_SRC

*** Update_index
#+BEGIN_SRC python
search.update_index()
search.update_index(Post)
# or
search.create_index(update=True)
search.create_index(Post, update=True)
#+END_SRC

*** Delete_index
#+BEGIN_SRC python
search.delete_index()
search.delete_index(Post)
# or
search.create_index(delete=True)
search.create_index(Post, delete=True)
#+END_SRC

*** Custom Analyzer
*only for whoosh backend*
#+BEGIN_SRC python
from jieba.analyse import ChineseAnalyzer
search = Search(analyzer=ChineseAnalyzer())
#+END_SRC

or use =__msearch_analyzer__= for special model
#+BEGIN_SRC python
class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['title', 'content', 'tag.name']
__msearch_analyzer__ = ChineseAnalyzer()
#+END_SRC

*** Custom index name
If you want to set special index name for some model.
#+BEGIN_SRC python
class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['title', 'content', 'tag.name']
__msearch_index__ = "post111"
#+END_SRC

*** Custom schema
#+BEGIN_SRC python
from whoosh.fields import ID

class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['title', 'content', 'tag.name']
__msearch_schema__ = {'title': ID(stored=True, unique=True), 'content': 'text'}
#+END_SRC

*Note:* if you use =hybrid_property=, default field type is =Text= unless set special =__msearch_schema__=

*** Custom parser
#+begin_src python
from whoosh.qparser import MultifieldParser

class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['title', 'content']

def _parser(fieldnames, schema, group, **kwargs):
return MultifieldParser(fieldnames, schema, group=group, **kwargs)

__msearch_parser__ = _parser
#+end_src

*Note:* Only for =MSEARCH_BACKEND= is =whoosh=

*** Custom index signal
*flask-msearch* uses flask signal to update index by default, if you want to use other asynchronous tools such as celey to update index, please set special =MSEARCH_INDEX_SIGNAL=
#+begin_src python
# app.py
app.config["MSEARCH_INDEX_SIGNAL"] = celery_signal
# or use string as variable
app.config["MSEARCH_INDEX_SIGNAL"] = "modulename.tasks.celery_signal"
search = Search(app)

# tasks.py
from flask_msearch.signal import default_signal

@celery.task(bind=True)
def celery_signal_task(self, backend, sender, changes):
default_signal(backend, sender, changes)
return str(self.request.id)

def celery_signal(backend, sender, changes):
return celery_signal_task.delay(backend, sender, changes)
#+end_src
** Relate index(*Experimental*)
for example
#+BEGIN_SRC python
class Tag(db.Model):
__tablename__ = 'tag'

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(49))

class Post(db.Model):
__tablename__ = 'post'
__searchable__ = ['title', 'content', 'tag.name']

id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(49))
content = db.Column(db.Text)

# one to one
tag_id = db.Column(db.Integer, db.ForeignKey('tag.id'))
tag = db.relationship(
Tag, backref=db.backref(
'post', uselist=False), uselist=False)

def __repr__(self):
return ''.format(self.title)
#+END_SRC

You must add *msearch_FUN* to Tag model,or the *tag.name* can't auto update.
#+BEGIN_SRC python
class Tag....
......
def msearch_post_tag(self, delete=False):
from sqlalchemy import text
sql = text('select id from post where tag_id=' + str(self.id))
return {
'attrs': [{
'id': str(i[0]),
'tag.name': self.name
} for i in db.engine.execute(sql)],
'_index': Post
}
#+END_SRC