Django项目使用Elasticsearch全文搜索引擎实现搜索优化

易小灯塔
2021-06-21 / 2 评论 / 2,178 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年06月30日,已超过879天没有更新,若内容或图片失效,请留言反馈。

Django项目使用Elasticsearch全文搜索引擎实现搜索优化

 

简介

由于项目需要用到模糊搜索, Mysql模糊查询正常情况下在数据量小的时候,速度还是可以的,数据表数据量大的时候就会查询时效率低下, 对此, 使用全文搜索引擎就是一个很好的解决方法.

Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析和探索的能力。

在 Django 项目中使用Elasticsearch有很多现成的库, 比如elasticsearch,django-elasticsearch-dsl, django-haystack , drf_haystack 等。

Haystack 是在 Django 中对接搜索引擎的框架,搭建了用户和搜索引擎之间的沟通桥梁。
我们在 Django 中可以通过使用 Haystack 来调用 Elasticsearch 搜索引擎。
Haystack 可以在不修改代码的情况下使用不同的搜索后端(比如 Elasticsearch、Whoosh、Solr等等)。
需要注意的是Haystack只支持es6以下的版本

准备

 

下载elasticsearch 2.4.6版本, 建议使用docker方式安装, 注意版本号

下载kibana 4.6.4版本,用于管理

下载对应版本的中文分词插件elasticsearch-analysis-ik-1.10.6.zip, 在es安装好下载的插件

下载地址

https://www.elastic.co/cn/elasticsearch/

https://www.elastic.co/cn/downloads/kibana

https://github.com/medcl/elasticsearch-analysis-ik/releases?page=13

 

docker镜像市场: http://hub.daocloud.io/

Docker安装

在服务器上新建配置文件docker-compose.yml

version: "2"
services: 
    elasticsearch: 
        image: daocloud.io/library/elasticsearch:2.6.4
        restart: always
        container_name: elasticserach
        ports: 
            - "9200:9200"
    kibana: 
        image: daocloud.io/library/kibana:4.6.4
        restart: always
        container_name: kibana
        ports: 
            - "5601:5601"
        environment: 
            - elasticsearch_url=http://127.0.0.1:9200
        depends_on: 
            - elasticsearch 

输入命令安装

docker-compose up -d 

安装分词插件

docker ps # 查看当前运行进程

docker exec -it es镜像id bash

cd bin
./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v2.6.4/elasticsearch-analysis-ik-1.10.6.zip 

重启es

docker restart es镜像id 

 

安装好Python需要的库

pip install django-haystack
pip install elasticsearch==2.4.1 # 注意版本2.4.1
pip install drf_haystack 

drf_haystack 文档

https://drf-haystack.readthedocs.io/en/latest/index.html

 

示例

1.配置

再设置里配置添加app

INSTALLED_APPS = [
    'haystack',
    ...
] 

配置链接

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
        'URL': 'http://127.0.0.1:9200/',    # 此处为elasticsearch运行的服务器ip地址和端口
        'INDEX_NAME': 'gameprop',           # 指定elasticserach建立的索引库名称
    },
}
# 搜索结果每页显示数量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5
# 实时更新index
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' 

2.创建haystack数据模型

app名/模块名目录下创建search_indexes.py文件,注意文件名必须使用search_indexes.py,代码如下:

from haystack import indexes
from Headlines.models import Article


class ArticleIndex(indexes.SearchIndex, indexes.Indexable):
    """文章索引模型类"""
    text = indexes.CharField(document=True, use_template=True)
    id = indexes.IntegerField(model_attr='id')
    createtime = indexes.DateTimeField(model_attr='createtime')
    content = indexes.CharField(model_attr='content')
    title = indexes.CharField(model_attr='title')

    def get_model(self):
        """返回建立索引的模型类"""
        return Article

    def index_queryset(self, using=None):
        """返回要建立索引的数据查询集"""
        return self.get_model().objects.all() 

3.创建 text 字段索引值模板文件

创建 text 字段索引值模板文件templates/search/indexes/APP名/模块名_text.txt

{{ object.id }}
{{ object.title }}
{{ object.channel }}
{{ object.labels }}
{{ object.content }} 

4.手动生成初始索引

在命令行中添加如下命令, 来手动生成索引表:

python manage.py rebuild_index 

5.编辑视图文件views.py

from drf_haystack.viewsets import HaystackViewSet
# 搜索文章
class SearchArticleViewSet(HaystackViewSet):
    # GET  /Headlines/search/?text=<搜索关键字>
    # 这里可以写多个模型,相应的:serializer里也可以写多个index_classes
    index_models = [Article]
    serializer_class = SearchArticleIndexSerializer 

6.编辑序列化器serializers.py

from drf_haystack import serializers as HSER
# 搜索文章
class SearchArticleIndexSerializer(HSER.HaystackSerializer):

    class Meta:
        index_classes = [ArticleIndex]  # 索引类的名称,可以有多个
        fields = ('text', 'content', 'id', 'title', 'createtime') 

7.编辑路由urls.py

# 搜索文章路由
from rest_framework.routers import DefaultRouter
from Headlines.views import SearchArticleViewSet

router = DefaultRouter()
router.register(r'Headlines/search', SearchArticleViewSet, base_name='search')
urlpatterns += router.urls 
5

评论 (2)

取消
  1. 头像
    666
    Windows 10 · Google Chrome

    新版本的不行嘛

    回复
    1. 头像
      insmoin 作者
      Windows 10 · Google Chrome
      @ 666

      es多个版本都有些区别, 不兼容, 好像只能支持到5.x

      回复