SolrJ 设置两个过滤条件,结果却像只生效了最后一个,先查看参数对象中的 fq 是否真的有两个值。连续 set 同一个参数名,与追加多值,不是一个动作。
两次 set 覆盖前值
旧代码的结构是:
org.apache.solr.client.solrj.SolrQuery query =
new org.apache.solr.client.solrj.SolrQuery("*:*");
query.set("fq", "id:[100001 TO 199999]");
query.set("fq", "cat:地理");
System.out.println(java.util.Arrays.toString(query.getParams("fq")));
第二次 set 替换了 fq 的值,调试时只剩 cat:地理。此时不应先怀疑范围语法或 Solr 没有执行 AND,因为发出的条件已经不完整。
改成追加,或者一次传入所有值
org.apache.solr.client.solrj.SolrQuery query =
new org.apache.solr.client.solrj.SolrQuery("*:*");
query.addFilterQuery("id:[100001 TO 199999]");
query.addFilterQuery("cat:地理");
System.out.println(java.util.Arrays.toString(query.getFilterQueries()));
还可以一次调用 setFilterQueries,设置完整列表:
query.setFilterQueries("id:[100001 TO 199999]", "cat:地理");
要点是后续再调用 setFilterQueries,仍是替换整组值,不是追加。SolrJ 8.0.0 中这两个入口分别委托给参数的 set 和 add。SolrQuery 对应源码
检查对象、请求与命中三层
先看 getFilterQueries(),再看最终请求是否携带两个 fq,最后在实际 schema 和数据上比较范围条件、分类条件及交集。只看返回列表,容易把构造参数阶段的问题误当成服务端查询问题。
多个 fq 的语义是过滤交集,不应把调用先后顺序描述为必然改变命中集合。不同条件的缓存与执行代价可以不同,但那是另外的问题。
字段和值还要符合查询契约
示例范围字段应具备对应类型,分类字段的分析方式也会影响匹配。如果值来自用户输入,应按所选查询解析器转义或构建查询,不能把任意字符串直接拼进语法。这里讨论的是 SolrQuery 的具体 API,不是所有名叫 set 的方法都一定具有相同语义。