|
|
|
|
@ -1,4 +1,25 @@
|
|
|
|
|
# encoding: utf-8
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
Whoosh 中文搜索后端模块
|
|
|
|
|
|
|
|
|
|
该模块为 Django Haystack 提供了一个基于 Whoosh 的中文搜索引擎后端实现。
|
|
|
|
|
主要特性包括:
|
|
|
|
|
|
|
|
|
|
- 支持中文分词搜索(使用 jieba 分词器)
|
|
|
|
|
- 实现了完整的搜索后端功能,包括索引创建、更新、删除和查询
|
|
|
|
|
- 支持多种数据类型的字段映射(文本、数字、日期、布尔值等)
|
|
|
|
|
- 提供搜索结果高亮显示功能
|
|
|
|
|
- 支持搜索建议和拼写纠正
|
|
|
|
|
- 支持多模型搜索和过滤
|
|
|
|
|
- 实现了 more_like_this 相似文档查找功能
|
|
|
|
|
|
|
|
|
|
依赖:
|
|
|
|
|
~~~~~~~~
|
|
|
|
|
- Whoosh >= 2.5.0
|
|
|
|
|
- jieba (用于中文分词)
|
|
|
|
|
- Django Haystack
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
|
|
|
|
|
|
@ -145,6 +166,18 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
self.setup_complete = True
|
|
|
|
|
|
|
|
|
|
def build_schema(self, fields):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
构建用于搜索索引的 Whoosh Schema 对象。
|
|
|
|
|
|
|
|
|
|
根据传入的字段定义创建对应的 Whoosh 字段类型,并最终构建一个完整的 Schema 实例。
|
|
|
|
|
|
|
|
|
|
:param fields: 包含字段名与字段配置对象的字典。键是字段名称,值是一个具有 field_type、stored、boost 等属性的对象。
|
|
|
|
|
|
|
|
|
|
:return: 第一个元素是文档内容字段名,第二个是构建好的 Whoosh Schema 对象。
|
|
|
|
|
|
|
|
|
|
:exception SearchBackendError: 当没有找到任何字段时抛出异常。
|
|
|
|
|
"""
|
|
|
|
|
schema_fields = {
|
|
|
|
|
ID: WHOOSH_ID(stored=True, unique=True),
|
|
|
|
|
DJANGO_CT: WHOOSH_ID(stored=True),
|
|
|
|
|
@ -200,6 +233,17 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
return (content_field_name, Schema(**schema_fields))
|
|
|
|
|
|
|
|
|
|
def update(self, index, iterable, commit=True):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
更新索引中的文档数据。
|
|
|
|
|
|
|
|
|
|
遍历可迭代对象中的模型实例,将其转换成可用于索引的数据格式并更新到索引中。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
index (SearchIndex): Haystack 的索引类实例。
|
|
|
|
|
iterable (iterable): 要被索引的模型实例集合。
|
|
|
|
|
commit (bool): 是否在更新后提交更改,默认为 **True**。
|
|
|
|
|
"""
|
|
|
|
|
if not self.setup_complete:
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
@ -245,6 +289,14 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
writer.commit()
|
|
|
|
|
|
|
|
|
|
def remove(self, obj_or_string, commit=True):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
从索引中删除指定文档。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
obj_or_string (Model | str): 要删除的模型实例或其唯一标识符字符串。
|
|
|
|
|
commit (bool): 是否立即提交更改,默认为 **True**。
|
|
|
|
|
"""
|
|
|
|
|
if not self.setup_complete:
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
@ -267,6 +319,14 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
exc_info=True)
|
|
|
|
|
|
|
|
|
|
def clear(self, models=None, commit=True):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
清除整个索引或特定模型类型的索引数据。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
models (list | tuple): 可选,要清除的模型列表。
|
|
|
|
|
commit (bool): 是否立即提交更改,默认为 **True**。
|
|
|
|
|
"""
|
|
|
|
|
if not self.setup_complete:
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
@ -304,6 +364,10 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
"Failed to clear Whoosh index: %s", e, exc_info=True)
|
|
|
|
|
|
|
|
|
|
def delete_index(self):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
完全删除当前索引目录下的文件并重新初始化索引结构。
|
|
|
|
|
"""
|
|
|
|
|
# Per the Whoosh mailing list, if wiping out everything from the index,
|
|
|
|
|
# it's much more efficient to simply delete the index files.
|
|
|
|
|
if self.use_file_storage and os.path.exists(self.path):
|
|
|
|
|
@ -315,6 +379,10 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
def optimize(self):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
对现有索引执行优化操作,提升查询性能。
|
|
|
|
|
"""
|
|
|
|
|
if not self.setup_complete:
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
@ -322,6 +390,17 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
self.index.optimize()
|
|
|
|
|
|
|
|
|
|
def calculate_page(self, start_offset=0, end_offset=None):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
根据偏移量计算分页信息。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
start_offset (int): 查询起始位置。
|
|
|
|
|
end_offset (int): 查询结束位置。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
tuple: 分别表示页码和每页长度。
|
|
|
|
|
"""
|
|
|
|
|
# Prevent against Whoosh throwing an error. Requires an end_offset
|
|
|
|
|
# greater than 0.
|
|
|
|
|
if end_offset is not None and end_offset <= 0:
|
|
|
|
|
@ -366,6 +445,33 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
limit_to_registered_models=None,
|
|
|
|
|
result_class=None,
|
|
|
|
|
**kwargs):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
执行全文检索操作。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
query_string (str): 用户输入的查询语句。
|
|
|
|
|
sort_by (list): 排序字段列表。
|
|
|
|
|
start_offset (int): 结果偏移起点。
|
|
|
|
|
end_offset (int): 结果偏移终点。
|
|
|
|
|
fields (str): 指定返回字段。
|
|
|
|
|
highlight (bool): 是否启用高亮显示。
|
|
|
|
|
facets (dict): 分面统计参数。
|
|
|
|
|
date_facets (dict): 时间范围分面参数。
|
|
|
|
|
query_facets (dict): 自定义查询分面参数。
|
|
|
|
|
narrow_queries (set): 过滤条件集合。
|
|
|
|
|
spelling_query (str): 用于拼写建议的原始查询。
|
|
|
|
|
within (tuple): 地理位置过滤参数。
|
|
|
|
|
dwithin (tuple): 距离范围内地理查询参数。
|
|
|
|
|
distance_point (tuple): 中心点坐标。
|
|
|
|
|
models (list): 限定搜索模型列表。
|
|
|
|
|
limit_to_registered_models (bool): 是否仅限注册过的模型。
|
|
|
|
|
result_class (class): 自定义结果封装类。
|
|
|
|
|
**kwargs: 其他扩展参数。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
dict: 包括匹配结果、命中数、拼写建议等信息。
|
|
|
|
|
"""
|
|
|
|
|
if not self.setup_complete:
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
@ -570,6 +676,23 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
limit_to_registered_models=None,
|
|
|
|
|
result_class=None,
|
|
|
|
|
**kwargs):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
查找与给定模型实例相似的内容。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
model_instance (Model): 目标模型实例。
|
|
|
|
|
additional_query_string (str): 补充查询语句。
|
|
|
|
|
start_offset (int): 起始偏移。
|
|
|
|
|
end_offset (int): 终止偏移。
|
|
|
|
|
models (list): 限制查找的模型列表。
|
|
|
|
|
limit_to_registered_models (bool): 是否只考虑已注册模型。
|
|
|
|
|
result_class (class): 自定义结果类。
|
|
|
|
|
**kwargs: 扩展参数。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
dict: 包含相似文档的结果集。
|
|
|
|
|
"""
|
|
|
|
|
if not self.setup_complete:
|
|
|
|
|
self.setup()
|
|
|
|
|
|
|
|
|
|
@ -682,6 +805,20 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
query_string='',
|
|
|
|
|
spelling_query=None,
|
|
|
|
|
result_class=None):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
处理原始搜索结果,转换为标准输出格式。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
raw_page (ResultsPage): 来自 Whoosh 的原始页面结果。
|
|
|
|
|
highlight (bool): 是否需要高亮关键词。
|
|
|
|
|
query_string (str): 查询语句。
|
|
|
|
|
spelling_query (str): 用于拼写的查询语句。
|
|
|
|
|
result_class (class): 自定义结果包装类。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
dict: 标准化的搜索响应结构。
|
|
|
|
|
"""
|
|
|
|
|
from haystack import connections
|
|
|
|
|
results = []
|
|
|
|
|
|
|
|
|
|
@ -768,6 +905,16 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def create_spelling_suggestion(self, query_string):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
生成针对用户查询的拼写修正建议。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
query_string (str): 输入的查询语句。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 拼写修正后的建议语句。
|
|
|
|
|
"""
|
|
|
|
|
spelling_suggestion = None
|
|
|
|
|
reader = self.index.reader()
|
|
|
|
|
corrector = reader.corrector(self.content_field_name)
|
|
|
|
|
@ -872,6 +1019,16 @@ class WhooshSearchBackend(BaseSearchBackend):
|
|
|
|
|
|
|
|
|
|
class WhooshSearchQuery(BaseSearchQuery):
|
|
|
|
|
def _convert_datetime(self, date):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
将日期时间对象转换为 Whoosh 可识别的字符串格式。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
date: 日期或日期时间对象。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 格式化后的日期时间字符串,格式为 `YYYYMMDDHHMMSS` 。
|
|
|
|
|
"""
|
|
|
|
|
if hasattr(date, 'hour'):
|
|
|
|
|
return force_str(date.strftime('%Y%m%d%H%M%S'))
|
|
|
|
|
else:
|
|
|
|
|
@ -903,6 +1060,20 @@ class WhooshSearchQuery(BaseSearchQuery):
|
|
|
|
|
return ' '.join(cleaned_words)
|
|
|
|
|
|
|
|
|
|
def build_query_fragment(self, field, filter_type, value):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
构建单个查询片段。
|
|
|
|
|
|
|
|
|
|
根据字段名、过滤类型和值构建相应的查询表达式片段,用于组合成完整的搜索查询。
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
field (str): 要查询的字段名。
|
|
|
|
|
filter_type (str): 过滤类型,如 `contains` 、 `exact` 、 `startswith` 等。
|
|
|
|
|
value: 要查询的值,可以是字符串、列表或其他数据类型。
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
str: 构建好的查询片段字符串。
|
|
|
|
|
"""
|
|
|
|
|
from haystack import connections
|
|
|
|
|
query_frag = ''
|
|
|
|
|
is_datetime = False
|
|
|
|
|
@ -1040,5 +1211,16 @@ class WhooshSearchQuery(BaseSearchQuery):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WhooshEngine(BaseEngine):
|
|
|
|
|
"""`xjj`
|
|
|
|
|
|
|
|
|
|
Whoosh 搜索引擎引擎类
|
|
|
|
|
|
|
|
|
|
该类继承自 ``BaseEngine``,用于集成 Whoosh 搜索功能,
|
|
|
|
|
包含搜索后端和查询处理的相关配置。
|
|
|
|
|
|
|
|
|
|
Attributes:
|
|
|
|
|
backend: 搜索后端类,设置为 `WhooshSearchBackend`
|
|
|
|
|
query: 查询类,设置为 `WhooshSearchQuery`
|
|
|
|
|
"""
|
|
|
|
|
backend = WhooshSearchBackend
|
|
|
|
|
query = WhooshSearchQuery
|
|
|
|
|
|