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 获取et和excel的版本号
Apr 09 Python
Python面向对象编程中的类和对象学习教程
Mar 30 Python
详解python的数字类型变量与其方法
Nov 20 Python
PyQt4实现下拉菜单可供选择并打印出来
Apr 20 Python
python使用xlrd模块读取xlsx文件中的ip方法
Jan 11 Python
如何安装并使用conda指令管理python环境
Jul 10 Python
对django 模型 unique together的示例讲解
Aug 06 Python
PYTHON EVAL的用法及注意事项解析
Sep 06 Python
python绘制彩虹图
Dec 16 Python
python实现超级玛丽游戏
Mar 18 Python
Python基于字典实现switch case函数调用
Jul 22 Python
Python 内置函数速查表一览
Jun 02 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实现的oracle分页函数实例
2016/01/25 PHP
PHP抓取淘宝商品的用户晒单评论+图片+搜索商品列表实例
2016/04/14 PHP
PHP判断表达式中括号是否匹配的简单实例
2016/10/22 PHP
php写入txt乱码的解决方法
2019/09/17 PHP
javascript模拟地球旋转效果代码实例
2013/12/02 Javascript
iframe父页面获取子页面参数的方法
2014/02/21 Javascript
详解JavaScript中的4种类型识别方法
2015/09/14 Javascript
深入浅析JavaScript中的constructor
2016/04/19 Javascript
javascript 分号总结及详细介绍
2016/09/24 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
2016/11/29 Javascript
浅析如何利用angular结合translate为项目实现国际化
2016/12/08 Javascript
jquery DataTable实现前后台动态分页
2017/06/17 jQuery
vue实现条件判断动态绑定样式的方法
2018/09/29 Javascript
vue+iview动态渲染表格详解
2019/03/19 Javascript
vue实现鼠标移入移出事件代码实例
2019/03/27 Javascript
[04:22]DSPL第二期精彩集锦:残血反杀!
2014/12/10 DOTA
[55:44]完美世界DOTA2联赛决赛 FTD vs Phoenix 第二场 11.08
2020/11/11 DOTA
Python中用startswith()函数判断字符串开头的教程
2015/04/07 Python
在Python的Flask框架下收发电子邮件的教程
2015/04/21 Python
在Python中操作时间之strptime()方法的使用
2020/12/30 Python
Python函数式编程指南(二):从函数开始
2015/06/24 Python
python获取外网ip地址的方法总结
2015/07/02 Python
Python实现ssh批量登录并执行命令
2016/10/25 Python
Python文本相似性计算之编辑距离详解
2016/11/28 Python
Python实现GUI学生信息管理系统
2020/04/05 Python
用Python写脚本,实现完全备份和增量备份的示例
2018/04/29 Python
[原创]Python入门教程1. 基本运算【四则运算、变量、math模块等】
2018/10/28 Python
对Python中TKinter模块中的Label组件实例详解
2019/06/14 Python
解决python 上传图片限制格式问题
2019/10/30 Python
Python实例教程之检索输出月份日历表
2020/12/16 Python
工商管理专业实习生自我鉴定
2013/09/29 职场文书
技校教师求职简历的自我评价
2013/10/20 职场文书
出国签证在职证明范本
2014/11/24 职场文书
2015年社区关工委工作总结
2015/04/03 职场文书
离婚起诉状范本
2015/05/19 职场文书
2015年入党积极分子培养考察意见
2015/08/12 职场文书