Solr function query过滤查询优化:区域值存在性校验方案咨询
Solr基于字段全量值的排除过滤规则实现方案
问题背景
业务规则
- 针对区域、国家设置文档排除规则,每份文档存储自身适用的排除值
- 若存在对应区域的排除规则,优先执行区域过滤查询
- 若不存在对应区域的排除规则,降级启用国家维度排除规则
现有实现&问题
现有过滤查询配置如下:
fq="!{!df=excluded_region v=$user.region}" fq={!frange l=0 u=0}and(not(docfreq(excluded_region,$user.region)),termfreq(excluded_country,$user.country))
存在的核心问题:当某个区域被完全从索引删除后,docFrequency 数值不会同步更新,导致规则生效异常。已知的可行方案均存在局限性:
- 段合并:索引体量过大无法执行
- 动态拼接过滤语句:不符合将拦截规则统一配置在请求处理器
appends节点的诉求
业务示例&预期效果
| DocId | excluded_region | excluded_country |
|---|---|---|
| Doc A | A1 | BE |
| Doc B | A2 | BE |
| Doc C | A3,A1 | BE |
| Doc D | A3,A1,A4 | BE |
预期效果:
- 若用户所属国家为BE、所属区域为A5(全索引无文档包含该区域值),无文档返回
- 若用户所属区域为A1,仅返回Doc B
解决方案
1. 更优的Function Query写法
直接替换docfreq依赖逻辑,用{!bool}过滤器实现规则,完全规避统计元数据不准的问题,同时支持直接配置在appends节点:
# 优先级1:过滤命中区域排除规则的文档 fq=-excluded_region:$user.region # 优先级2:仅当区域规则不存在时触发国家排除规则 fq={!bool must='-excluded_country:$user.country' filter='-{!term f=excluded_region v=$user.region}'}
该写法的优势:
- 基于实时文档匹配结果判断,不依赖段级统计数据,删除操作后规则不会失效
- 过滤器查询可被Solr缓存,查询性能远高于function query实现
2. 跨全文档校验指定区域是否存在的实现
用query()函数做子查询校验区域是否存在,可直接嵌入过滤规则:
# 子查询判断用户区域是否存在匹配文档,返回1代表存在,0代表不存在 {!frange l=1}query($region_exist_check) region_exist_check=excluded_region:$user.region
结合需求的完整配置如下:
# 校验区域存在 + 过滤区域排除文档 fq={!bool must='-excluded_region:$user.region' must='{!frange l=1}query($region_exist_check)'} region_exist_check=excluded_region:$user.region # 区域不存在时触发国家过滤 fq={!bool must='-excluded_country:$user.country' filter='{!frange u=0}query($region_exist_check)'}
该配置完全符合预期效果:
- 用户区域为A5时,
region_exist_check返回0,第一层过滤器校验不通过,全量文档被过滤返回空 - 用户区域为A1时,第一层过滤器过滤掉所有
excluded_region包含A1的文档(DocA、DocC、DocD),仅返回DocB
内容的提问来源于stack exchange,提问作者DavidVdd
相关产品推荐
相关产品推荐

