flask-web 搜索系统项目实际应用suggest查询实现联想提示自动补全的实现

Posted 胖虎是只mao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flask-web 搜索系统项目实际应用suggest查询实现联想提示自动补全的实现相关的知识,希望对你有一定的参考价值。

一、项目全文检索实现

elasticsearch python客户端使用
https://elasticsearch-py.readthedocs.io/en/master/>

pip install elasticsearch

对于elasticsearch 5.x 版本 需要按以下方式导入

from elasticsearch5 import Elasticsearch

# elasticsearch集群服务器的地址
ES = [
    '127.0.0.1:9200'
]

# 创建elasticsearch客户端
es = Elasticsearch(
    ES,
    # 启动前嗅探es集群服务器
    sniff_on_start=True,
    # es集群服务器结点连接异常时是否刷新es结点信息
    sniff_on_connection_fail=True,
    # 每60秒刷新结点信息
    sniffer_timeout=60
)

搜索使用方式

query = {
    'query': {
        'bool': {
            'must': [
                {'match': {'_all': 'python web'}}
            ],
            'filter': [
                {'term': {'status': 2}}
            ]
        }
    }
}
ret = es.search(index='articles', doc_type='article', body=query)

项目搜索接口视图实现
在toutiao-backend/toutiao/resources/search目录中新建search.py

from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_restful import inputs
from flask import g, current_app
from redis.exceptions import RedisError

from . import constants
from cache import article as cache_article
from cache import user as cache_user
from models.user import Search
from models import db

class SearchResource(Resource):
    """
    搜索结果
    """
    def get(self):
        """
        获取搜索结果
        """
        qs_parser = RequestParser()
        qs_parser.add_argument('q', type=inputs.regex(r'^.{1,50}$'), required=True, location='args')
        qs_parser.add_argument('page', type=inputs.positive, required=False, location='args')
        qs_parser.add_argument('per_page', type=inputs.int_range(constants.DEFAULT_SEARCH_PER_PAGE_MIN, constants.DEFAULT_SEARCH_PER_PAGE_MAX, 'per_page'), required=False, location='args')
        args = qs_parser.parse_args()
        q = args.q
        page = 1 if args.page is None else args.page
        per_page = args.per_page if args.per_page else constants.DEFAULT_SEARCH_PER_PAGE_MIN

        # Search from Elasticsearch
        query = {
            'from': (page-1)*per_page,
            'size': per_page,
            '_source': False,
            'query': {
                'bool': {
                    'must': [
                        {'match': {'_all': q}}
                    ],
                    'filter': [
                        {'term': {'status': 2}}
                    ]
                }
            }
        }
        ret = current_app.es.search(index='articles', doc_type='article', body=query)

        total_count = ret['hits']['total']

        results = []

        hits = ret['hits']['hits']
        for result in hits:
            article_id = int(result['_id'])
            article = cache_article.ArticleInfoCache(article_id).get()
            if article:
                results.append(article)

        # Record user search history
        if g.user_id and page == 1:
            try:
                cache_user.UserSearchingHistoryStorage(g.user_id).save(q)
            except RedisError as e:
                current_app.logger.error(e)

        return {'total_count': total_count, 'page': page, 'per_page': per_page, 'results': results}

在toutiao-backend/toutiao/resources/search目录中新建constants.py

# 搜索结果分页默认每页数量 下限
DEFAULT_SEARCH_PER_PAGE_MIN = 10

# 搜索结果页默认每页数量 上限
DEFAULT_SEARCH_PER_PAGE_MAX = 50

添加ES新文章索引数据
在自媒体平台发布文章接口中,除了保存文章外,还要向es库中添加新文章的索引

doc = {
          'article_id': article.id,
          'user_id': article.user_id,
          'title': article.title,
          'content': article.content.content,
          'status': article.status,
          'create_time': article.ctime
      }
current_app.es.index(index='articles', doc_type='article', body=doc, id=article.id)

suggest查询

联想提示

1 拼写纠错
对于已经建立的articles索引库,elasticsearch还提供了一种查询模式,suggest建议查询模式

curl 127.0.0.1:9200/articles/article/_search?pretty -d '
{
    "from": 0,
    "size": 10,
    "_source": false,
    "suggest": {
        "text": "phtyon web",
        "word-phrase": {
            "phrase": {
                "field": "_all",
                "size": 1
            }
        }
    }
}'

当我们输入错误的关键词phtyon web时,es可以提供根据索引库数据得出的正确拼写python web

2 自动补全

使用elasticsearch提供的自动补全功能,因为文档的类型映射要特殊设置,所以原先建立的文章索引库不能用于自动补全,需要再建立一个自动补全的索引库

curl -X PUT 127.0.0.1:9200/completions -H 'Content-Type: application/json' -d'
{
   "settings" : {
       "index": {
           "number_of_shards" : 3,
           "number_of_replicas" : 1
       }
   }
}
'
curl -X PUT 127.0.0.1:9200/completions/_mapping/words -H 'Content-Type: application/json' -d'
{
     "words": {
          "properties": {
              "suggest": {
                  "type": "completion",
                  "analyzer": "ik_max_word"
              }
          }
     }
}
'

使用logstash导入初始数据
编辑logstash_mysql_completion.conf

input{
     jdbc {
         jdbc_driver_library => "/home/python/mysql-connector-java-8.0.13/mysql-connector-java-8.0.13.jar"
         jdbc_driver_class => "com.mysql.jdbc.Driver"
         jdbc_connection_string => "jdbc:mysql://127.0.0.1:3306/toutiao?tinyInt1isBit=false"
         jdbc_user => "root"
         jdbc_password => "mysql"
         jdbc_paging_enabled => "true"
         jdbc_page_size => "1000"
         jdbc_default_timezone =>"Asia/Shanghai"
         statement => "select title as suggest from news_article_basic"
         clean_run => true
     }
}
output{
      elasticsearch {
         hosts => "127.0.0.1:9200"
         index => "completions"
         document_type => "words"
      }
}

执行命令导入数据

sudo /usr/share/logstash/bin/logstash -f ./logstash_mysql_completion.conf

自动补全建议查询

curl 127.0.0.1:9200/completions/words/_search?pretty -d '
{
    "suggest": {
        "title-suggest" : {
            "prefix" : "pyth", 
            "completion" : { 
                "field" : "suggest" 
            }
        }
    }
}
'

curl 127.0.0.1:9200/completions/words/_search?pretty -d '
{
    "suggest": {
        "title-suggest" : {
            "prefix" : "python web", 
            "completion" : { 
                "field" : "suggest" 
            }
        }
    }
}
'

三、项目suggest查询实现

思路

先将关键字在completions 自动补全索引库中查询,获取建议的补全信息
如没有获取到补全信息,可能表示用户输入的关键词有拼写错误,在articles索引库中进行纠错建议查询

实现

在toutiao-backend/toutiao/resources/search.py中实现自动补全视图

class SuggestionResource(Resource):
    """
    联想建议
    """
    def get(self):
        """
        获取联想建议
        """
        qs_parser = RequestParser()
        qs_parser.add_argument('q', type=inputs.regex(r'^.{1,50}$'), required=True, location='args')
        args = qs_parser.parse_args()
        q = args.q

        # 先尝试自动补全建议查询
        query = {
            'from': 0,
            'size': 10,
            '_source': False,
            'suggest': {
                'word-completion': {
                    'prefix': q,
                    'completion': {
                        'field': 'suggest'
                    }
                }
            }
        }
        ret = current_app.es.search(index='completions', body=query)
        options = ret['suggest']['word-completion'][0]['options']

        # 如果没得到查询结果,进行纠错建议查询
        if not options:
            query = {
                'from': 0,
                'size': 10,
                '_source': False,
                'suggest': {
                    'text': q,
                    'word-phrase': {
                        'phrase': {
                            'field': '_all',
                            'size': 1
                        }
                    }
                }
            }
            ret = current_app.es.search(index='articles', doc_type='article', body=query)
            options = ret['suggest']['word-phrase'][0]['options']

        results = []
        for option in options:
            if option['text'] not in results:
                results.append(option['text'])

        return {'options': results}

ES库中的数据来源

  • 运行前 logstash导入初始数据

  • 对于程序运行中新产生的数据添加到es库

    • haystack

      django settings 配置文件

      ​ haystack_realtime_process_signal

      作用 在django中增删改数据库数据的时候,haystack将数据也会同步到es库中

    • 不使用haystack 自己操作python es客户端的时候

      自己在保存数据库数据的时候,自己写入es库

以上是关于flask-web 搜索系统项目实际应用suggest查询实现联想提示自动补全的实现的主要内容,如果未能解决你的问题,请参考以下文章

flask-web Redis缓存实际项目中的应用

flask-web APScheduler 定时任务以及实际应用

flask-web—— 搜索系统Elasticsearch分布式搜索引擎原理分片与集群IK中文分析器索引与文档Logstash导入数据与查询

基于搜索推荐系统根据用户搜索频率(热搜)排序

flask-web ——对象存储——图片上传存储传输等

flask-web—— JWT认证方案