{"id":13421615,"url":"https://github.com/honmaple/flask-msearch","last_synced_at":"2025-04-05T07:04:54.597Z","repository":{"id":45585557,"uuid":"88359759","full_name":"honmaple/flask-msearch","owner":"honmaple","description":"Full text search for flask.","archived":false,"fork":false,"pushed_at":"2024-01-16T05:07:23.000Z","size":109,"stargazers_count":225,"open_issues_count":8,"forks_count":30,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-29T06:06:30.808Z","etag":null,"topics":["flask","search","sqlalchemy","whoosh"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/honmaple.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-15T16:31:48.000Z","updated_at":"2025-03-12T07:37:14.000Z","dependencies_parsed_at":"2024-06-19T00:10:07.669Z","dependency_job_id":"317bc1d2-e4be-4564-beca-8c1bd5051274","html_url":"https://github.com/honmaple/flask-msearch","commit_stats":{"total_commits":48,"total_committers":5,"mean_commits":9.6,"dds":0.125,"last_synced_commit":"45c576cf393fb4d2eee500102d583f7989ba3473"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/honmaple%2Fflask-msearch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/honmaple%2Fflask-msearch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/honmaple%2Fflask-msearch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/honmaple%2Fflask-msearch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/honmaple","download_url":"https://codeload.github.com/honmaple/flask-msearch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247299831,"owners_count":20916190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","search","sqlalchemy","whoosh"],"created_at":"2024-07-30T23:00:26.910Z","updated_at":"2025-04-05T07:04:54.570Z","avatar_url":"https://github.com/honmaple.png","language":"Python","readme":"* flask-msearch\n  [[https://pypi.python.org/pypi/Flask-Msearch][https://img.shields.io/badge/pypi-v0.2.9.4-brightgreen.svg]]\n  [[https://python.org][https://img.shields.io/badge/python-2/3-brightgreen.svg]]\n  [[LICENSE][https://img.shields.io/badge/license-BSD-blue.svg]]\n\n** Installation\n   To install flask-msearch:\n\n   #+BEGIN_SRC shell\n   pip install flask-msearch\n   # when MSEARCH_BACKEND = \"whoosh\"\n   pip install whoosh blinker\n   # when MSEARCH_BACKEND = \"elasticsearch\", only for 6.x.x\n   pip install elasticsearch==6.3.1\n   #+END_SRC\n\n   Or alternatively, you can download the repository and install manually by doing:\n   #+BEGIN_SRC sehll\n   git clone https://github.com/honmaple/flask-msearch\n   cd flask-msearch\n   python setup.py install\n   #+END_SRC\n\n** Quickstart\n   #+BEGIN_SRC python\n     from flask_msearch import Search\n     [...]\n     search = Search()\n     search.init_app(app)\n\n     # models.py\n     class Post(db.Model):\n         __tablename__ = 'post'\n         __searchable__ = ['title', 'content']\n\n     # views.py\n     @app.route(\"/search\")\n     def w_search():\n         keyword = request.args.get('keyword')\n         results = Post.query.msearch(keyword,fields=['title'],limit=20).filter(...)\n         # or\n         results = Post.query.filter(...).msearch(keyword,fields=['title'],limit=20).filter(...)\n         # elasticsearch\n         keyword = \"title:book AND content:read\"\n         # more syntax please visit https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html\n         results = Post.query.msearch(keyword,limit=20).filter(...)\n         return ''\n   #+END_SRC\n\n** Config\n\n   #+BEGIN_SRC python\n     # when backend is elasticsearch, MSEARCH_INDEX_NAME is unused\n     # flask-msearch will use table name as elasticsearch index name unless set __msearch_index__\n     MSEARCH_INDEX_NAME = 'msearch'\n     # simple,whoosh,elaticsearch, default is simple\n     MSEARCH_BACKEND = 'whoosh'\n     # table's primary key if you don't like to use id, or set __msearch_primary_key__ for special model\n     MSEARCH_PRIMARY_KEY = 'id'\n     # auto create or update index\n     MSEARCH_ENABLE = True\n     # logger level, default is logging.WARNING\n     MSEARCH_LOGGER = logging.DEBUG\n     # SQLALCHEMY_TRACK_MODIFICATIONS must be set to True when msearch auto index is enabled\n     SQLALCHEMY_TRACK_MODIFICATIONS = True\n     # when backend is elasticsearch\n     ELASTICSEARCH = {\"hosts\": [\"127.0.0.1:9200\"]}\n   #+END_SRC\n\n** Usage\n   #+BEGIN_SRC python\n     from flask_msearch import Search\n     [...]\n     search = Search()\n     search.init_app(app)\n\n     class Post(db.Model):\n         __tablename__ = 'basic_posts'\n         __searchable__ = ['title', 'content']\n\n         id = db.Column(db.Integer, primary_key=True)\n         title = db.Column(db.String(49))\n         content = db.Column(db.Text)\n\n         def __repr__(self):\n             return '\u003cPost:{}\u003e'.format(self.title)\n   #+END_SRC\n\n   if raise *sqlalchemy ValueError*,please pass db param to Search\n   #+BEGIN_SRC python\n  db = SQLalchemy()\n  search = Search(db=db)\n   #+END_SRC\n\n\n*** Create_index\n    #+BEGIN_SRC sh\n   search.create_index()\n   search.create_index(Post)\n    #+END_SRC\n\n*** Update_index\n    #+BEGIN_SRC python\n    search.update_index()\n    search.update_index(Post)\n    # or\n    search.create_index(update=True)\n    search.create_index(Post, update=True)\n    #+END_SRC\n\n*** Delete_index\n    #+BEGIN_SRC python\n    search.delete_index()\n    search.delete_index(Post)\n    # or\n    search.create_index(delete=True)\n    search.create_index(Post, delete=True)\n    #+END_SRC\n\n*** Custom Analyzer\n    *only for whoosh backend*\n    #+BEGIN_SRC python\n      from jieba.analyse import ChineseAnalyzer\n      search = Search(analyzer=ChineseAnalyzer())\n    #+END_SRC\n\n    or use =__msearch_analyzer__= for special model\n    #+BEGIN_SRC python\n      class Post(db.Model):\n          __tablename__ = 'post'\n          __searchable__ = ['title', 'content', 'tag.name']\n          __msearch_analyzer__ = ChineseAnalyzer()\n    #+END_SRC\n\n*** Custom index name\n    If you want to set special index name for some model.\n    #+BEGIN_SRC python\n     class Post(db.Model):\n         __tablename__ = 'post'\n         __searchable__ = ['title', 'content', 'tag.name']\n         __msearch_index__ = \"post111\"\n    #+END_SRC\n\n*** Custom schema\n    #+BEGIN_SRC python\n     from whoosh.fields import ID\n\n     class Post(db.Model):\n         __tablename__ = 'post'\n         __searchable__ = ['title', 'content', 'tag.name']\n         __msearch_schema__ = {'title': ID(stored=True, unique=True), 'content': 'text'}\n    #+END_SRC\n\n    *Note:* if you use =hybrid_property=, default field type is =Text= unless set special =__msearch_schema__=\n\n*** Custom parser\n    #+begin_src python\n      from whoosh.qparser import MultifieldParser\n\n      class Post(db.Model):\n          __tablename__ = 'post'\n          __searchable__ = ['title', 'content']\n\n          def _parser(fieldnames, schema, group, **kwargs):\n              return MultifieldParser(fieldnames, schema, group=group, **kwargs)\n\n          __msearch_parser__ = _parser\n    #+end_src\n\n    *Note:* Only for =MSEARCH_BACKEND= is =whoosh=\n\n*** Custom index signal\n    *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=\n    #+begin_src python\n      # app.py\n      app.config[\"MSEARCH_INDEX_SIGNAL\"] = celery_signal\n      # or use string as variable\n      app.config[\"MSEARCH_INDEX_SIGNAL\"] = \"modulename.tasks.celery_signal\"\n      search = Search(app)\n\n      # tasks.py\n      from flask_msearch.signal import default_signal\n\n      @celery.task(bind=True)\n      def celery_signal_task(self, backend, sender, changes):\n          default_signal(backend, sender, changes)\n          return str(self.request.id)\n\n      def celery_signal(backend, sender, changes):\n          return celery_signal_task.delay(backend, sender, changes)\n    #+end_src\n** Relate index(*Experimental*)\n   for example\n   #+BEGIN_SRC python\n     class Tag(db.Model):\n         __tablename__ = 'tag'\n\n         id = db.Column(db.Integer, primary_key=True)\n         name = db.Column(db.String(49))\n\n     class Post(db.Model):\n         __tablename__ = 'post'\n         __searchable__ = ['title', 'content', 'tag.name']\n\n         id = db.Column(db.Integer, primary_key=True)\n         title = db.Column(db.String(49))\n         content = db.Column(db.Text)\n\n         # one to one\n         tag_id = db.Column(db.Integer, db.ForeignKey('tag.id'))\n         tag = db.relationship(\n             Tag, backref=db.backref(\n                 'post', uselist=False), uselist=False)\n\n         def __repr__(self):\n             return '\u003cPost:{}\u003e'.format(self.title)\n   #+END_SRC\n\n   You must add *msearch_FUN* to Tag model,or the *tag.name* can't auto update.\n   #+BEGIN_SRC python\n   class Tag....\n     ......\n     def msearch_post_tag(self, delete=False):\n         from sqlalchemy import text\n         sql = text('select id from post where tag_id=' + str(self.id))\n         return {\n             'attrs': [{\n                 'id': str(i[0]),\n                 'tag.name': self.name\n             } for i in db.engine.execute(sql)],\n             '_index': Post\n         }\n   #+END_SRC\n","funding_links":[],"categories":["Third-Party Extensions","Flask Utilities","Python","Full-text searching"],"sub_categories":["Full-text Search"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhonmaple%2Fflask-msearch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhonmaple%2Fflask-msearch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhonmaple%2Fflask-msearch/lists"}