Django整合ElasticSearch,实现数据的快速检索(有代码)

2022-06-06 08:03:21 浏览数 (1)

这里写目录标题

  • 1 背景
  • 2 Haystack 是什么
  • 3 安装相关包,与配置
  • 4 开启es和es可视化工具
  • 5 生成索引
  • 6 改代码

1 背景

Haystack 的官网

代码语言:javascript复制
https://django-haystack.readthedocs.io/en/master/

2 Haystack 是什么

这个就是一个工具,就是连接django和es的中间的一个东西, Haystack 为 Django 提供模块化搜索。它具有统一、熟悉的 API,允许您插入不同的搜索后端(例如Solr、 Elasticsearch、Whoosh、Xapian等),而无需修改代码。

3 安装相关包,与配置

代码语言:javascript复制
pip install drf-haystack
pip install elasticsearch==7.6.0

安装的elashsearch 版本要和你本地的一样,在启动的时候报错,就是确实依赖,提示缺少什么安装什么,最后都安装好之后,

1 注册应用

代码语言:javascript复制
INSTALLED_APPS = [
    ...
    'haystack',
    ...
]

就是要把haystack当做APP注册到项目里面

2 配置

在配置文件中配置haystack使用的搜索引擎后端

本地不同的es,就需要不同的版本,这个去官网找

3 之后创建索引类,这个就是和django里面model一样,因为model里面的每一个类代表一个表,所以我们需要新建一个文件夹,放es里面的实体类

在你对应要创建索引的表的APP的根目录下,创建这个文件

文件的名称必须是这个

代码语言:javascript复制
search_indexes.py

里面的内容是

代码语言:javascript复制
# 索引模型类的名称必须是 模型类名称   Index
from haystack import indexes
from .models import jtsgb

# 必须继承  indexes.SearchIndex, indexes.Indexable
class jtsgbIndex(indexes.SearchIndex, indexes.Indexable):
    # 以下的字段,是es里面对应的字段
    # 第一个必须这样写
    text = indexes.CharField(document=True, use_template=True)
# 下面的就是和你model里面的一样了
    name = indexes.CharField(model_attr='name')
    zzxm = indexes.CharField(model_attr='zzxm')
#  必须这个写,返回的就是你的model名称
    def get_model(self):
        """返回建立索引的模型类"""
        return jtsgb

# 返回你的查询的结果,可以改成一定的条件的,但是格式就是这样
    def index_queryset(self, using=None):
        """返回要建立索引的数据查询集"""
        return self.get_model().objects.all()

4 在templates目录中创建text字段使用的模板文件 目录结构必须是这样

object可以理解为模型类的对象,搜索时,可以根据这三个字段来搜索,就是你es搜索,会根据那些字段进行查询,就会在这个文件里面配

以上都弄好之后,启动你的es,还有可视化工具

4 开启es和es可视化工具

5 生成索引

我们在django项目里面相当于已经集成了es,也配置了一些东西,那么现在就需要使用项目在es软件里面生成索引

手动生成初始索引

代码语言:javascript复制
python manage.py rebuild_index

或者直接在pycharm软件里面,按照这个步骤

如果不报错,那么就成功了,就打开es软件

看到已经生成了索引库

并且索引库里面有数据了,rebuild_index 这个命令就是将我们MySQL数据库里面的数据同步到es里面,之后我们查询的的就是es,不是mysql了,所以我们在操作完mysql数据库之后,要及时的同步数据,或者写个定时器,进行同步数据;

6 改代码

我们现在完成的是将django集成了es,但是我们自己写的页面查询功能,如果改为查询es了?

第一步: 写个路由,view里面是类的形式,路由里面,类的后面一定要加括号

第二步,写对应的后台接口,就是写view

代码语言:javascript复制
# 一定要继承SearchView
class MySearchView(SearchView):
    
    # 重写人家的方法
    def create_response(self):
        # 人家的,就这样写,获取到的就是全部的东西
        context = self.get_context()
        data_list = []
        #   context['page'].object_list   这样获取到的就是  数据的list集合
        for sku in context['page'].object_list:
            
            # 获取表里面的数据,就是前缀就是sku.object
            print(sku.object.name)
            data_list.append({
                'id': sku.object.id,
                'name': sku.object.name,
                'zzxm':sku.object.name,
                'gszy':sku.object.gszy,
                'sglx_id':sku.object.sglx_id,
                'gmrq': sku.object.gmrq,
                'ydsl': sku.object.ydsl,
                'description': sku.object.description,
                'thumbnail': sku.object.thumbnail,
                'desc_pack': sku.object.desc_pack,
            })
        content = {}
        if data_list:
            content = {

                'active_menu': 'homepage',
                'xw_list': data_list,
            }
        else:
            xw_list = jtsgb.objects.all()[0:1]


            content = {

                'active_menu': 'homepage',
                'xw_list': xw_list,
            }

        # 渲染到我们自己写的页面
        return render(self.request, 'index1.html', {"context":context,"content":content})

以上就开发完成一个接口。现在看前端,因为查询功能,前端需要模糊查询,而且还有分页,这个功能咋实现

首先我们要知道,我们可以在settings.py里面配置每页显示的数量 搜索结果每页显示数量 HAYSTACK_SEARCH_RESULTS_PER_PAGE = 3

前端往后端传的名称,必须是q

因为要实现分页功能,所以,我们先看接口返回的是什么

一个是自己封装的,一个是人家的,所以我们要实现分页,就需要用他的东西

代码语言:javascript复制
                        {% if context.page.has_previous %}
                            <li class="previous"><a
                                    href="?q={{ context.query }}&amp;page={{ context.page.previous_page_number }}">上一页</a>
                            </li>
                        {% else %}
                            <li class="previous disabled"><a href="#">上一页</a></li>
                        {% endif %}
                        第 {{ context.page.number }} / {{ context.page.paginator.num_pages }}页
                        {% if context.page.has_next %}
                            <li class="next"><a
                                    href="?q={{ context.query }}&amp;page={{ context.page.next_page_number }}">下一页</a>
                            </li>
                        {% else %}
                            <li class="next disabled"><a href="#">下一页</a></li>
                        {% endif %}

以上就实现了前后端的分离,与集成,如何判断他一定就是查询的es,而不是mysql,我们可以将mysql数据改了,看下查询出来的是什么,如果还是原来的,就是查询了es了,除非你重新更新了es了

0 人点赞