Django集成搜索引擎Elasticserach的方法示例


Posted in Python onJune 04, 2019

1.背景

当用户在搜索框输入关键字后,我们要为用户提供相关的搜索结果。可以选择使用模糊查询 like 关键字实现,但是 like 关键字的效率极低。查询需要在多个字段中进行,使用 like 关键字也不方便,另外分词的效果也不理想。

全文检索方案

  • 全文检索即在指定的任意字段中进行检索查询。
  • 全文检索方案需要配合搜索引擎来实现。

搜索引擎原理

  • 搜索引擎 进行全文检索时,会对数据库中的数据进行一遍预处理,单独建立起一份 索引结构数据 。
  • 索引结构数据 类似字典的索引检索页 ,里面包含了关键词与词条的对应关系,并记录词条的位置。
  • 搜索引擎进行全文检索时,将 关键字在索引数据中进行快速对比查找,进而找到数据的真实存储位置 。

2.Elasticsearch介绍

实现全文检索的搜索引擎,首选的是 Elasticsearch 。

  • Elasticsearch 是用 Java 实现的,开源的搜索引擎。
  • 它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github等都采用它。
  • Elasticsearch 的底层是开源库Lucene。但是,没法直接使用 Lucene,必须自己写代码去调用它的接口。

分词说明

搜索引擎在对数据构建索引时,需要进行分词处理。

分词是指将一句话拆解成 多个单字 或 词 ,这些字或词便是这句话的关键词。

Elasticsearch 不支持对中文进行分词建立索引,需要配合扩展 elasticsearch-analysis-ik 来实现中文分词处理。

3.集成Elasticsearch

3.1. Haystack介绍和安装配置

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

Haystack安装

$ pip install django-haystack
$ pip install elasticsearch==2.4.1

Haystack注册应用和路由

在 django 的配置文件中注册。

INSTALLED_APPS = [ 'haystack', # 全文检索注册]​

在总路由中新建 haystack 的路由。

urlpatterns = [url(r'^search/', include('haystack.urls')),]

Haystack配置

在配置文件中配置Haystack为搜索引擎后端

# Haystack
HAYSTACK_CONNECTIONS = {
 'default': {
  'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
  'URL': 'http://192.168.103.158:9200/', # Elasticsearch服务器ip地址,端口号固定为9200
  'INDEX_NAME': 'serach_mall', # Elasticsearch建立的索引库的名称
 },
}

# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 搜索的每页大小
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 3

HAYSTACK_SIGNAL_PROCESSOR 配置项保证了在Django运行起来后,有新的数据产生时,Haystack仍然可以让Elasticsearch实时生成新数据的索引。

3.2 Haystack建立数据索引

1.创建索引类

通过创建索引类,来指明让搜索引擎对哪些字段建立索引,也就是可以通过哪些字段的关键字来检索数据。

本项目中对模型类SKU信息进行全文检索,所以在 该模型类的应用(goods)中 新建 search_indexes.py 文件,用于存放索引类。索引类必须继承 haystack.indexes.SearchIndex 与 haystack.indexes.Indexable .

from haystack import indexes

from .models import SKU


class SKUIndex(indexes.SearchIndex, indexes.Indexable):
 """SKU索引数据模型类"""
 text = indexes.CharField(document=True, use_template=True)

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

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

索引类 SKUIndex 说明:

  • 在 SKUIndex 建立的字段,都可以借助 Haystack 由 Elasticsearch 搜索引擎查询。
  • 其中 text 字段我们声明为 document=True ,表名该字段是主要进行关键字查询的字段。
  • text 字段的索引值可以由多个数据库模型类字段组成,具体由哪些模型类字段组成,我们用 use_template=True 表示后续通过模板来指明。

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

在项目 templates 目录中创建 text字段 使用的模板文件

具体在 templates/search/indexes/goods/sku_text.txt 文件中定义,其中 goods 为应用名, sku_text.txt 中的 sku 为模型类小写。

{{ object.id }}
{{ object.name }}
{{ object.caption }}

模板文件说明:当将关键词通过text参数名传递时

此模板指明SKU的 id 、 name 、 caption 作为 text 字段的索引值来进行关键字索引查询。

3.手动生成初始索引

$ python manage.py rebuild_index

第一次需要生成索引需要执行上述命令,后续会自动生成索引。

3.3 全文检索测试

准备测试表单

  • 请求方法: GET
  • 请求地址: /search/
  • 请求参数: q
<div class="search_wrap fl">
 <form method="get" action="/search/" class="search_con">
  <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
  <input type="submit" class="input_btn fr" name="" value="搜索">
 </form>
 ...
 ...
</div>

然后在 templates/search/ 目录下新建 search.html 接收和渲染全文检索的结果 .

3.4 渲染搜索结果

Haystack返回的数据包括:

  • query :搜索关键字
  • paginator :分页paginator对象
  • page :当前页的page对象(遍历 page 中的对象,可以得到 result 对象)
  • result.objects : 当前遍历出来的SKU对象。
<div class="main_wrap clearfix">
 <div class=" clearfix">
  <ul class="goods_type_list clearfix">
   {% for result in page %}
   <li>
    {# object取得才是sku对象 #}
    <a href="/detail/{{ result.object.id }}/" rel="external nofollow" rel="external nofollow" ><img src="{{ result.object.default_image.url }}"></a>    
    <h4><a href="/detail/{{ result.object.id }}/" rel="external nofollow" rel="external nofollow" >{{ result.object.name }}</a></h4>
    <div class="operate">
     <span class="price">¥{{ result.object.price }}</span>
     <span>{{ result.object.comments }}评价</span>
    </div>
   </li>
   {% else %}
    <p>没有找到您要查询的商品。</p>
   {% endfor %}
  </ul>
  <div class="pagenation">
   <div id="pagination" class="page"></div>
  </div>
 </div>
</div>

这里Elasticsearch替我们把django中的视图函数写了。

搜索页分页器

<div class="main_wrap clearfix">
 <div class=" clearfix">
  ......
  <div class="pagenation">
   <div id="pagination" class="page"></div>
  </div>
 </div>
</div>

<script type="text/javascript">
 $(function () {
  $('#pagination').pagination({
   currentPage: {{ page.number }},
   totalPage: {{ paginator.num_pages }},
   callback:function (current) {
    window.location.href = '/search/?q={{ query }}&page=' + current;
   }
  })
 });
</script>

这里使用的 jquery.pagination.js 接收要渲染的数据,当然也可以使用其他框架的分页器或自定义的来接收。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
netbeans7安装python插件的方法图解
Dec 24 Python
使用grappelli为django admin后台添加模板
Nov 18 Python
Python实现的维尼吉亚密码算法示例
Apr 12 Python
浅谈python requests 的put, post 请求参数的问题
Jan 02 Python
Python面向对象程序设计类变量与成员变量、类方法与成员方法用法分析
Apr 12 Python
python3.8 微信发送服务器监控报警消息代码实现
Nov 05 Python
django rest framework serializer返回时间自动格式化方法
Mar 31 Python
Python包和模块的分发详细介绍
Jun 19 Python
基于Python的一个自动录入表格的小程序
Aug 05 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
Aug 18 Python
pip已经安装好第三方库但pycharm中import时还是标红的解决方案
Oct 09 Python
python实现批量提取指定文件夹下同类型文件
Apr 05 Python
python添加菜单图文讲解
Jun 04 #Python
Python3.6+Django2.0以上 xadmin站点的配置和使用教程图解
Jun 04 #Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
Jun 04 #Python
pandas DataFrame索引行列的实现
Jun 04 #Python
深入浅析Python中的迭代器
Jun 04 #Python
Python学习笔记之读取文件、OS模块、异常处理、with as语法示例
Jun 04 #Python
Python利用sqlacodegen自动生成ORM实体类示例
Jun 04 #Python
You might like
《星际争霸II》全新指挥官斯台特曼现已上线
2020/03/08 星际争霸
YII Framework框架教程之使用YIIC快速创建YII应用详解
2016/03/15 PHP
PHP类相关知识点实例总结
2016/09/28 PHP
Yii框架页面渲染操作实例详解
2019/07/19 PHP
网站导致浏览器崩溃的原因总结(多款浏览器) 推荐
2010/04/15 Javascript
javascript 文本框水印/占位符(watermark/placeholder)实现方法
2012/01/15 Javascript
js函数的引用, 关于内存的开销
2012/09/17 Javascript
jquery设置控件位置的方法
2013/08/21 Javascript
js中的如何定位固定层的位置
2014/06/15 Javascript
深入分析下javascript中的[]()+!
2015/07/07 Javascript
jQuery EasyUI 菜单与按钮之创建简单的菜单和链接按钮
2015/11/18 Javascript
使用jQuery.form.js/springmvc框架实现文件上传功能
2016/05/12 Javascript
Angular.Js中ng-include指令的使用与实现
2017/05/07 Javascript
Vue 2.0在IE11中打开项目页面空白的问题解决
2017/07/16 Javascript
JS实现快递单打印功能【推荐】
2018/06/21 Javascript
Node.js 如何利用异步提升任务处理速度
2019/01/07 Javascript
Vue CLI3基础学习之pages构建多页应用
2019/06/02 Javascript
vue获取验证码倒计时组件
2019/08/26 Javascript
解决使用layui对select append元素无效或者未及时更新的问题
2019/09/18 Javascript
微信小程序批量监听输入框对按钮样式进行控制的实现代码
2019/10/12 Javascript
jQuery实现手风琴效果(蒙版)
2020/01/11 jQuery
详解Vue 的异常处理机制
2020/11/30 Vue.js
Python中函数的参数传递与可变长参数介绍
2015/06/30 Python
详解Python中 sys.argv[]的用法简明解释
2017/12/20 Python
解决pandas 作图无法显示中文的问题
2018/05/24 Python
Python拆分大型CSV文件代码实例
2019/10/07 Python
Python 类,property属性(简化属性的操作),@property,property()用法示例
2019/10/12 Python
python时间与Unix时间戳相互转换方法详解
2020/02/13 Python
如何在django中实现分页功能
2020/04/22 Python
Python通过kerberos安全认证操作kafka方式
2020/06/06 Python
MySQL面试题
2014/01/12 面试题
培训主管岗位职责
2014/02/01 职场文书
房地产广告词大全
2014/03/19 职场文书
实习生工作证明范本
2014/09/14 职场文书
公司食堂管理制度
2015/08/05 职场文书
Mysql分库分表之后主键处理的几种方法
2022/02/15 MySQL