1、搜索技术简介
- 结构化数据检索----可以使用SQL的模糊查询 like 关键字
查询需要在多个字段中进行
使用 like 关键字也不方便
like 关键字的效率极低
like 关键字不能对查询得到的多个结果进行较好的排序 - 全文检索
全文搜索是用于搜索非结构化数据的一种搜索技术,比如通过关键字搜索多个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中包含了我们搜索的数据。