新版博客SEO优化基本完成,新老博客内容正在整合中,保证每篇文章高质量。 SiteMap RSS Github
Django项目之Elasticsearch搜索引擎以及elasticsearch-ik配置
嘉美伯爵   2019年10月9日 15:06   数据库   ElasticSearch ik   54  

由于haystack只支持到es2.0,因此我们在安装es的时候选择2.0的版本,这里推荐docker安装,不需要关jdk和ik等环境,这里我们只使用haystack中的对象的

安装es-ik

# 拉取
docker pull grantchen/elasticsearch-ik
# 启动
docker run -d -p 9200:9200 -p 9300:9300 --restart always --name elasticsearch -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx64m"  grantchen/elasticsearch-ik

修改源码

  • 修改haystack源码的elasticsearch_backend.py,将分词器snowball改为ik

  • 添加索引信息

我看了haystack的源码,haystack创建的时候并不支持suggest的字段创建,但是支持查询,这里我们可以手动添加

# _mapping/modelresult
{
    "properties":{
        "suggest":{
            "type":"completion",
            "analyzer":"ik"
        }
    }
}
  • 修改haystack源码的signals.py

发布文章的时候生成suggest,这里的做法是截取django发给haystack的信号量,即修改handle_save函数即可

from elasticsearch import Elasticsearch
import json
client = Elasticsearch(hosts=["139.199.123.96"])
essay_id = instance.id
essay_title = instance.title
ik_response = client.indices.analyze(index='essay', body={"analyzer": "ik", "text": essay_title})
analyzed_words = set([r["token"] for r in ik_response["tokens"] if len(r["token"]) > 1])
suggestions = json.dumps({'doc': {"suggest": {'input': list(analyzed_words), 'weight': 10}}})
client.update(index='essay', doc_type='modelresult', id='essay.essay.{}'.format(essay_id), body=suggestions)
  • 测试是否成功

由于haystack对es和中文分词都太友好,因此我们不使用haystack.urls中的SearchView函数,这里对搜索结果实现模糊识别的效果

  • 数据结构
{
                "result": [
                    {
                        "id": 1,
                        "title": "文章标题"
                    }

                ]
            }
  • 视图代码
from django.views.generic.base import View
import json
from elasticsearch import Elasticsearch

client = Elasticsearch(hosts=["139.199.123.96"])


class FuzzyView(View):
    def get(self, request):
        key_words = request.GET.get('q', '')
        re_datas = []
        if key_words:
            query_string = {
                "query": {
                    "fuzzy": {
                        "title": {
                            "value": key_words,
                            "fuzziness": 2
                        }
                    }
                }
            }
            se_response = client.search(index='essay', body=query_string)
            for item in se_response['hits']['hits']:
                tmp_dict = {}
                source = item['_source']
                tmp_dict['id'] = source['django_id']
                tmp_dict['title'] = source["title"]
                re_datas.append(tmp_dict)
        return HttpResponse(json.dumps({'result': re_datas}), content_type="application/json")
  • 路由代码
url(r'search/$', FuzzyView.as_view(), name='search')
  • 测试接口

参考文档

Django项目之Elasticsearch搜索引擎

python – Django haystack EdgeNgramField给出了与elasticsearch不同的结果