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 相关文章推荐
Python编程之多态用法实例详解
May 19 Python
Python删除windows垃圾文件的方法
Jul 14 Python
Python中强大的命令行库click入门教程
Dec 26 Python
python中类变量与成员变量的使用注意点总结
Apr 29 Python
python爬虫获取百度首页内容教学
Dec 23 Python
python SQLAlchemy的Mapping与Declarative详解
Jul 04 Python
浅析Django 接收所有文件,前端展示文件(包括视频,文件,图片)ajax请求
Mar 09 Python
python输入一个水仙花数(三位数) 输出百位十位个位实例
May 03 Python
Python  word实现读取及导出代码解析
Jul 09 Python
python安装sklearn模块的方法详解
Nov 28 Python
python工具快速为音视频自动生成字幕(使用说明)
Jan 27 Python
解决numpy和torch数据类型转化的问题
May 23 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
php中的静态变量的基本用法
2014/03/20 PHP
使用GDB调试PHP代码,解决PHP代码死循环问题
2015/03/02 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
Thinkphp5.0 框架实现控制器向视图view赋值及视图view取值操作示例
2019/10/12 PHP
几行代码轻松搞定jquery实现flash8类似的连接效果
2007/05/03 Javascript
终于解决了IE8不支持数组的indexOf方法
2013/04/03 Javascript
jquery ajax方式直接提交整个表单核心代码
2013/08/15 Javascript
js+css 实现遮罩居中弹出层(随浏览器窗口滚动条滚动)
2013/12/11 Javascript
JS实现按比例缩放图片的方法(附C#版代码)
2015/12/08 Javascript
用JS实现图片轮播效果代码(一)
2016/06/26 Javascript
javascript学习笔记_浅谈基础语法,类型,变量
2016/09/19 Javascript
vue.js初学入门教程(1)
2016/11/03 Javascript
js实现3d悬浮效果
2017/02/16 Javascript
jQuery EasyUI开发技巧总结
2017/09/26 jQuery
es6在react中的应用代码解析
2017/11/08 Javascript
解决vue无法设置滚动位置的问题
2018/10/07 Javascript
vue 关闭浏览器窗口的时候,清空localStorage的数据示例
2019/11/06 Javascript
微信小程序实现选择地址省市区三级联动
2020/06/21 Javascript
详解element-ui动态限定的日期范围选择器代码片段
2020/07/03 Javascript
Vue-cli assets SubDirectory及PublicPath区别详解
2020/08/18 Javascript
Python实现的一个找零钱的小程序代码分享
2014/08/25 Python
Python实现CET查分的方法
2015/03/10 Python
python pandas中DataFrame类型数据操作函数的方法
2018/04/08 Python
Python判断一个三位数是否为水仙花数的示例
2018/11/13 Python
Python math库 ln(x)运算的实现及原理
2019/07/17 Python
Django单元测试工具test client使用详解
2019/08/02 Python
django数据模型on_delete, db_constraint的使用详解
2019/12/24 Python
pyinstaller打包成无控制台程序时运行出错(与popen冲突的解决方法)
2020/04/15 Python
浅谈keras中loss与val_loss的关系
2020/06/22 Python
python 解决pycharm运行py文件只有unittest选项的问题
2020/09/01 Python
python 检测nginx服务邮件报警的脚本
2020/12/31 Python
英国最大的百货公司:Harrods
2016/08/18 全球购物
2015年扶贫帮困工作总结
2015/05/20 职场文书
2016年9月份红领巾广播稿
2015/12/21 职场文书
简短的人生哲理(38句)
2019/08/13 职场文书
纯CSS3实现div按照顺序出入效果
2021/07/15 HTML / CSS