简介
业务场景
搜索栏输入塑料玩具
时,希望优先搜索出 名称 或 简介 中带有 塑料玩具
的条目, 并同时匹配出 塑料
、玩具
、玩具塑料
、塑料玩巨
等信息,按照匹配度排序,且支持匹配英文大小写。
技术选型
Django自带的模糊匹配 icontains 表示 Mysql的 like,不满足业务分词需求,且随着数据量增大,消耗的资源和时间都会线性增长,因此考虑使用专门的搜索框架
- haystack
搜索框架,用于接入搜索引擎,而无需关注索引建立、搜索解析等细节问题。支持whoosh、elastic search等 - whoosh
轻量级全文搜索引擎 - Elasticsearch
重量级全文搜索引擎,对服务器性能占用较多,暂不考虑 - jieba
用于替换whoosh自带的分词器,以支持中文分词
安装配置
pip install django-haystack
pip install whoosh
pip install jieba
# settings.py
INSTALLED_APPS = (
...
'haystack', #将haystack放在最后
)
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine', # 如覆写了Whoosh引擎,则此处为自定义引擎位置
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),# 索引文件位置
}
}
# 监听Django更新数据库数据,自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 查询加载数据量 默认为 10
HAYSTACK_ITERATOR_LOAD_PER_QUERY = 500
# 默认为AND
HAYSTACK_DEFAULT_OPERATOR = 'OR'
search_indexes.py
在需要全文搜索的应用目录下,新增search_indexes.py
文件
- document=True
每个索引类中只能有一个字段具有该属性,haystack将使用此字段的内容作为索引进行检索(primary field)。通常将该字段命名为text
- use_template=True
为模型中,/templates/search/indexes/应用名称/模型类名称_text.txt
文件中的字段创建索引
如下,前端在索引的时候,可以按照text=xxx,也可以按照id=xxx,name=xxx等,我们的数据返回也是返回id,name,price
# search_indexes.py
from haystack import indexes
from .models import Blog # 引入自己的model
# 类名必须为需要检索的Model名+Index
class BlogIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
# 此外可以存在,可以不存在,看具体需要的数据
id = indexes.IntegerField(model_attr='id')
name = indexes.CharField(model_attr='name')
price = indexes.DecimalField(model_attr='price')
def get_model(self):
return Blog # 添加自己model
def index_queryset(self, using=None):
return self.get_model().objects.filter(is_delete=0)
# templates/search/indexes/blog/blog_text.txt
{{ object.title }}
{{ object.body }}
使用 jieba 中文分词
复制haystack/backends/whoosh_backend.py
到自己的app 路径下,并添加修改如下内容:
# 顶部引入jieba中的中文分词器
from jieba.analyse import ChineseAnalyzer
# 在整个py文件中,查找
analyzer=StemmingAnalyzer()
全部改为改为
analyzer=ChineseAnalyzer()
总共大概有两三处吧
修改完成后,应修改settings.py
中ENGINE指向该新文件
使用命令首次生成索引
python manage.py rebuild_index
在view中使用
class VisitorQuotationView(viewsets.GenericViewSet):
# 列表数据
def list(self, request, *args, **kwargs):
key = request.GET.get('key', "")
all_results = SearchQuerySet().auto_query(key).models(Quotation)
return Response({'data': all_results }, status=status.HTTP_200_OK)
网友评论