电商系统中的商品搜索功能(Django+Haystack+Elasticsearch)

1、搜索技术简介

  1. 结构化数据检索----可以使用SQL的模糊查询 like 关键字
    查询需要在多个字段中进行
    使用 like 关键字也不方便
    like 关键字的效率极低
    like 关键字不能对查询得到的多个结果进行较好的排序
  2. 全文检索
    全文搜索是用于搜索非结构化数据的一种搜索技术,比如通过关键字搜索多个word文件内容中哪些文件包含这个关键字,搜索多个邮件内容中哪些邮件包含这个关键字等等
    全文搜索有两种方法:
    1、顺序扫描,何为顺序扫描?比如要找的内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头到尾,如果此文档包含此字符串,则此文档就是我们要找的文件,接着看下一个文件,直至扫描完所有的文件,这种方法简单直接,适合 小数据量 ,大数据量就比较慢,数据库中的搜索就是顺序扫描法。
    2、索引法,将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定的结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分非结构化数据中提取出来的然后重新组织的信息,我们称之索引。
    比如字典,字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找到一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只是几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按照结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据,即对字的解释,这就是全文检索技术。

这样看下来,全文检索的方式很明显更加的高效,功能也更加的丰富,那么怎么来实现全文检索这个功能呢?

全文检索方案可以使用搜索引擎来实现。

接下来我们来认识搜索引擎。

2、Elasticsearch

Elasticsearch就是一种可以实现全文检索的搜索引擎。它是用Java实现的,开源的搜索引擎。它可以快速地存储、搜索和分析海量的数据,维基百科、GitHub、今日头条等都采用它。
搜索引擎对数据构建索引时,需要进行分词处理。分词是指对一句话拆解成多个单字或词,这些字或词就是这句话的关键字。比如:“我是中国人”,分词后,“我”、“是”、“中”、“国”、“人”、“中国”等等都可以是这句话的关键字。
而Elasticsearch不支持对中文进行分词建立索引,需要配合扩展 elasticsearch-analysis-ik 来实现中文分词处理。

3、使用Docker安装Elasticsearch

1、获取Elasticsearch-ik镜像

sudo docker image pull delron/elasticsearch-ik:2.4.6-1.0

2、运行Elasticsearch-ik

docker run -dti -p 9200:9200 -p 9300:9300 --name elasticsearch delron/elasticsearch-ik:2.4.6-1.0

3、测试

打开浏览器,输入localhost:9200

出现如下界面,部署完成。
在这里插入图片描述

4、Haystack

1、Haystack介绍
在上面,我们完成了Elasticsearch的安装和启动,但是怎么把Elasticsearch这个搜索引擎的功能用在我们的Django项目中,直接去用其实是比较复杂的,所以我们可以通过第三方的应用来建立我们的Django项目和Elasticsearch搜索引擎直接的关联,在这里,我们采用Haystack这个第三方应用。
Haystack是在Django中对接搜索引擎的框架,搭建了用户和搜索引擎之间的沟通桥梁,在Django中我们可以通过Haystack来调用Elasticsearch搜索引擎的功能。
Haystack可以在不修改代码的情况下使用不同的搜索后端(比如Elasticsearch、Whoosh、Solr等)
在这里插入图片描述

2、Haystack安装

pip install django-haystack
pip install elasticsearch==2.4.1

3、Haystack注册应用和配置路由

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

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

# settings.py

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

# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

ENGINE是用来为haystack配置搜索引擎后端驱动的,目前配置Elasticsearch为搜索引擎
HAYSTACK_SIGNAL_PROCESSOR配置项保证了在Django运行起来后,有新的数据产生时,Haystack可以让Elasticsearch实时生成新的数据索引

5、为Haystack建立数据索引

1、定义索引模型类
通过索引模型类,来指明让搜索引擎对哪些字段建立索引,也就是可以通过哪些字段的数据来提取关键字建立检索数据。
本项目中对SKU信息进行全文检索,所以在 goods 应用中新建 search_indexes.py 文件(名字不能改哦),用于存放索引类。

from haystack import indexes

from goods.models import SKU
'''
1、我们需要在 模型对应的 子应用中 创建 search_index.py文件 以方便haystack来检索数据
2、索引类必须继承自 indexes.SearchIndex, indexes.Indexable
3、必须定义一个字段 document=True
	字段名 起什么都可以 text只是一个惯例
	所有的索引的 这个字段 都一致就行
4、use_template=True
	允许我们单独设置一个文件,来指定哪些字段进行检索
	这个单独的文件创建在 模版文件夹下/search/indexes/子应用名目录/模型类名小写_text.txt
'''
class SKUIndexModel(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)

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

重新两个函数,如上。

2、创建索引值模版文件
在templates目录中创建 text 字段使用的模版文件
具体在 templates/search/indexes/goods/sku_text.txt 文件中定义

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

在将关键字通过 text 参数名传递时,此模版指明了SKU的 id、name、caption 作为 text 字段的索引值来进行关键字索引查询。

3、手动生成初始索引

python3 manage.py rebuild_index

在这里插入图片描述

6、实现搜索功能

请求方法:GET
请求地址:/search/
请求参数:q

定义搜索的视图函数SKUSearchView()

'''
我们是借助于 haystack 来对接 elasticsearch
所以 haystack 可以帮助我们 查询数据
所以 我们的视图函数继承的是haystack的SearchView
'''
from haystack.views import SearchView

class SKUSearchView(SearchView):

	'''
	重新create_response()方法
	为什么??
	create_response原先返回的是相应的数据
	不是json数据
	所以 重写
	'''
    def create_response(self):
        context = self.get_context()
        return JsonResponse({"code":0, "errmsg":"ok"})

添加子路由

# goods urls.py
path('search/', SKUSearchView()),

最后,通过 断点 调试,可以看到context中包含了我们搜索的数据。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值