# 相关性检索优化说明 ## 概述 本次优化将相关性检索从简单的 `must` 子句中的 `multi_match` 查询,改为使用 `should` 子句的多查询策略,参考了成熟的搜索实现,显著提升了检索效果。 ## 主要改进 ## 实现方式 本次优化采用精简实现,直接在 `QueryParser` 中集成必要的分析功能,不新增独立模块。 ### 1. 查询结构优化 **之前的结构**(效果差): ```json { "bool": { "must": [ { "multi_match": { "query": "戏水动物", "fields": ["title_zh^3.0", "brief_zh^1.5", ...], "minimum_should_match": "67%", "tie_breaker": 0.9, "boost": 1, "_name": "base_query" } } ] } } ``` **优化后的结构**(效果更好): ```json { "bool": { "should": [ { "multi_match": { "_name": "base_query", "fields": ["title_zh^3.0", "brief_zh^1.5", ...], "minimum_should_match": "75%", "operator": "AND", "query": "戏水动物", "tie_breaker": 0.9 } }, { "multi_match": { "_name": "base_query_trans_en", "boost": 0.4, "fields": ["title_en^3.0", ...], "minimum_should_match": "75%", "operator": "AND", "query": "water sports", "tie_breaker": 0.9 } }, { "multi_match": { "query": "戏水动物", "fields": ["title_zh^3.0", "brief_zh^1.5", ...], "type": "phrase", "slop": 2, "boost": 1.0, "_name": "phrase_query" } }, { "multi_match": { "query": "戏水 动物", "fields": ["title_zh^3.0", "brief_zh^1.5", ...], "operator": "AND", "tie_breaker": 0.9, "boost": 0.1, "_name": "keywords_query" } } ], "minimum_should_match": 1 } } ``` ### 2. 集成查询分析功能 在 `QueryParser` 中直接集成必要的分析功能: - **关键词提取**:使用 HanLP 提取查询中的名词(长度>1),用于关键词查询(可选,HanLP 不可用时降级) - **查询类型判断**:区分短查询和长查询 - **Token 计数**:用于判断查询长度 ### 3. 多查询策略 #### 3.1 基础查询(base_query) - 使用 `operator: "AND"` 确保所有词都必须匹配 - `minimum_should_match: "75%"` 提高匹配精度 - 使用 `tie_breaker: 0.9` 进行分数融合 #### 3.2 翻译查询(base_query_trans_zh/en) - 当查询语言不是中文/英文时,添加翻译查询 - 使用较低的 boost(0.4)避免过度影响 - 支持跨语言检索 #### 3.3 短语查询(phrase_query) - 针对短查询(token_count >= 2 且 is_short_query) - 使用 `type: "phrase"` 进行精确短语匹配 - 支持 slop(允许词序调整) #### 3.4 关键词查询(keywords_query) - 使用 HanLP 提取的名词进行查询 - 仅在关键词长度合理时启用(避免关键词占查询比例过高) - 使用较低的 boost(0.1)作为补充 #### 3.5 长查询优化(long_query) - 当前已禁用(参考实现中也是 False) - 未来可根据需要启用 ### 4. 字段映射优化 新增 `_get_match_fields()` 方法,支持: - 根据语言动态获取匹配字段 - 区分全部字段(all_fields)和核心字段(core_fields) - 核心字段用于短语查询和关键词查询,提高精度 ## 实现细节 ### 文件修改清单 1. **修改文件**: - `query/query_parser.py` - 添加关键词提取、查询类型判断等功能(HanLP 可选) - `search/es_query_builder.py` - 实现 should 子句的多查询策略 - `search/searcher.py` - 传递 parsed_query 给查询构建器 ### 关键参数说明 - **minimum_should_match**: 从 "67%" 提升到 "75%",提高匹配精度 - **operator**: 从默认改为 "AND",确保所有词都匹配 - **tie_breaker**: 保持 0.9,用于分数融合 - **boost 值**: - base_query: 1.0(默认) - translation queries: 0.4 - phrase_query: 1.0 - keywords_query: 0.1 ### 依赖要求 - **HanLP**(可选):如果安装了 `hanlp` 包,会自动启用关键词提取功能 ```bash pip install hanlp ``` 如果未安装,系统会自动降级到简单分析(基于空格分词),不影响基本功能。 - **HanLP 模型**:首次运行时会自动下载 - Tokenizer: `CTB9_TOK_ELECTRA_BASE_CRF` - POS Tagger: `CTB9_POS_ELECTRA_SMALL` ### 配置说明 - **忽略关键词**:在 `_extract_keywords()` 方法中配置 - 默认忽略:`['玩具']` ## 使用示例 ### 基本使用 查询会自动使用优化后的策略,无需额外配置: ```python # 在 searcher.py 中,查询会自动使用优化策略 result = searcher.search( query="戏水动物", tenant_id="162", size=10 ) ``` ### 查看分析结果 可以直接从 `parsed_query` 查看分析结果: ```python parsed_query = query_parser.parse("戏水动物") print(f"关键词: {parsed_query.keywords}") print(f"Token数: {parsed_query.token_count}") print(f"短查询: {parsed_query.is_short_query}") print(f"长查询: {parsed_query.is_long_query}") ``` ## 性能考虑 1. **HanLP 初始化**:采用懒加载,首次使用时才初始化 2. **错误处理**:HanLP 初始化失败或未安装时,系统会降级到简单分析(基于空格分词),不影响服务 3. **代码精简**:所有功能直接集成在 `QueryParser` 中,无额外模块依赖 ## 后续优化方向 1. **长查询优化**:可以启用长查询的特殊处理 2. **意图识别**:完善意图词典,提供更精准的意图识别 3. **参数调优**:根据实际效果调整 boost 值和 minimum_should_match 4. **A/B 测试**:对比优化前后的检索效果 ## 注意事项 1. **HanLP 依赖**:HanLP 是可选的,如果未安装或初始化失败,系统会自动降级到简单分析,不会影响基本功能 2. **性能影响**:HanLP 分析会增加一定的处理时间,但采用懒加载机制 3. **字段匹配**:确保 ES 索引中存在对应的中英文字段 4. **代码精简**:所有功能都集成在现有模块中,保持代码结构简洁 ## 参考 - 参考实现中的查询构建逻辑 - HanLP 官方文档:https://hanlp.hankcs.com/ - Elasticsearch multi_match 查询文档