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中enumerate函数用法实例分析
May 20 Python
python的pdb调试命令的命令整理及实例
Jul 12 Python
Python使用文件锁实现进程间同步功能【基于fcntl模块】
Oct 16 Python
python正则实现提取电话功能
Feb 24 Python
python selenium 对浏览器标签页进行关闭和切换的方法
May 21 Python
Python 通过打码平台实现验证码的实现
May 13 Python
django 中的聚合函数,分组函数,F 查询,Q查询
Jul 25 Python
django自带调试服务器的使用详解
Aug 29 Python
Python实现元素等待代码实例
Nov 11 Python
解决torch.autograd.backward中的参数问题
Jan 07 Python
python缩进长度是否统一
Aug 02 Python
Python读取文件夹下的所有文件实例代码
Apr 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
Apache中php.ini的设置方法
2013/02/28 PHP
PHP内置的Math函数效率测试
2014/12/01 PHP
使用laravel指定日志文件记录任意日志
2019/10/17 PHP
JavaScript中出现乱码的处理心得
2009/12/24 Javascript
使用Javascript接收get传递的值的代码
2011/11/30 Javascript
js获取指定字符前/后的字符串简单实例
2016/10/27 Javascript
jQuery实现base64前台加密解密功能详解
2017/08/29 jQuery
微信小程序使用request网络请求操作实例
2017/12/15 Javascript
JS加密插件CryptoJS实现AES加密操作示例
2018/08/16 Javascript
使用layui+ajax实现简单的菜单权限管理及排序的方法
2019/09/10 Javascript
关于Vue中axios的封装实例详解
2019/10/20 Javascript
vue props 单项数据流实例分享
2020/02/16 Javascript
从零开始在vue-cli4配置自适应vw布局的实现
2020/06/08 Javascript
Python中的字符串查找操作方法总结
2016/06/27 Python
PyQt5每天必学之布局管理
2018/04/19 Python
Python函数返回不定数量的值方法
2019/01/22 Python
Python3模拟curl发送post请求操作示例
2019/05/03 Python
Python_查看sqlite3表结构,查询语句的示例代码
2019/07/17 Python
python开头的coding设置方法
2019/08/08 Python
Python3 元组tuple入门基础
2020/02/09 Python
opencv+python实现鼠标点击图像,输出该点的RGB和HSV值
2020/06/02 Python
python将字典内容写入json文件的实例代码
2020/08/12 Python
python中random.randint和random.randrange的区别详解
2020/09/20 Python
HTML5中的postMessage API基本使用教程
2016/05/20 HTML / CSS
韩国女装NO.1网店:STYLENANDA
2016/09/16 全球购物
Skyscanner阿联酋:全球领先的旅游搜索平台
2017/11/25 全球购物
Fossil德国官网:化石手表、手袋、珠宝及配件
2019/12/07 全球购物
医学类导师推荐信范文
2013/11/19 职场文书
门卫班长岗位职责
2013/12/15 职场文书
化妆师职业生涯规划书
2014/02/16 职场文书
《逃家小兔》教学反思
2014/02/23 职场文书
快递员岗位职责
2014/09/12 职场文书
师德师风个人总结
2015/02/06 职场文书
文化苦旅读书笔记
2015/06/29 职场文书
python3 字符串str和bytes相互转换
2022/03/23 Python
pd.drop_duplicates删除重复行的方法实现
2022/06/16 Python