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

简介

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

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

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

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

需要注意的是Haystack只支持 Elasticsearch 6以下的版本

准备

可以选择手动安装或docker安装, 推荐使用docker方式安装

1.手动下载安装

Elasticsearch 6以下的版本(可以下载5.x, 我这里用2.4.6版本, 如果是5.x要和kibana还有分词插件对应版本)

下载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

2.Docker安装

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

在服务器上新建配置文件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/v1.10.6/elasticsearch-analysis-ik-1.10.6.zip

重启es

docker restart es镜像id 

3.安装好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': 'Article',           # 指定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

你可能感兴趣的:(Django项目使用Elasticsearch全文搜索引擎实现搜索优化)