如果我理解正确,您需要这样的查询
+body:hello +(+body:test -header:xy)
解释为
+body:hello +(body:test -body:xy)
.
为此,您可以编写一个替换器方法,该方法遍历解析树并在到达包含字段名称的对象时替换字段(例如 Term、PhraseQuery、SpanNearQuery 或任何您拥有的)。
在 Java 中,您只能通过反射更改这些类中对象的字段名称。另一种选择是使用其他字段名称克隆已解析的树。
您可以编写一个“替换器方法”,它接受一个查询对象并根据查询类型(即布尔查询、短语查询、术语查询......)处理它。
- 如果是布尔查询,您可以遍历子句并将子查询递归地委托给替换方法。
- 如果是术语查询,您可以替换术语中的字段。
- 如果是短语查询,您可以替换查询中的字段。
- 等等……
如果您选择克隆方式,您的方法将改为返回一个新对象。
编辑:
下面是 Java 的示例代码,有 4 种查询类型(不考虑提升):
public static Query forceField(Query q, String field) {
if(q instanceof BooleanQuery) {
BooleanQuery newQ = new BooleanQuery();
for (BooleanClause clause : (BooleanQuery)q) {
newQ.add(forceField(clause.getQuery(), field), clause.getOccur());
}
return newQ;
}else if(q instanceof TermQuery) {
return new TermQuery(new Term(field, ((TermQuery)q).getTerm().text()));
}else if(q instanceof PhraseQuery) {
PhraseQuery phraseQuery = new PhraseQuery();
Term[] terms = ((PhraseQuery)q).getTerms();
for (int i = 0; i < terms.length; i++) {
phraseQuery.add(new Term(field, terms[i].text()), ((PhraseQuery)q).getPositions()[i]);
}
return phraseQuery;
}else if(q instanceof WildcardQuery) {
return new WildcardQuery(new Term(field, ((WildcardQuery)q).getTerm().text()));
} else {
throw new UnsupportedOperationException("Query type not known: " + q.getClass());
}
}
另一个不太干净的选项是使用整个查询的 toString 并替换其中的所有字段并再次解析它。