我正在使用Lucene.Net3.0.3,需要在一个特定的字段中进行搜索(忽略查询中指定的任何字段)。我得到了一个经过解析的Lucene查询,所以我无法生成一个带有所需字段的经过解析的查询。Lucene中是否有任何功能可以让我循环查询的术语并更改字段?给定的查询将是一个复杂的查询,其中将有跨度,子句等。或者,可能有某种方法强制Lucene忽略解析查询中给出的字段,只使用指定的字段。
rjzwgtxy1#
如果我没有理解错的话,您需要一个如下的查询
+body:hello +(+body:test -header:xy)
解释为
+body:hello +(body:test -body:xy)
。为此,您可以编写一个replacer方法,该方法遍历解析的树,并在到达包含字段名的对象时替换字段(例如Term、PhraseQuery、SpanNearQuery或您拥有的任何对象)。在Java中,你只能通过反射来改变那些类中对象的字段名,另一个选择是用其他字段名来克隆解析后的树。您可以编写一个“replacer方法”,它接受一个查询对象,并根据查询类型(例如,布尔查询、短语查询、术语查询等)处理它。
如果你选择克隆的方式,你的方法将返回一个新的对象。编辑:下面是一个具有4种查询类型的Java示例代码(不考虑提升):
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,替换其中的所有字段,然后再次解析。
mrphzbgm2#
如果将来有人遇到这种情况,一个更干净的解决方案将是创建一个新的查询解析器,并使用该字段重新解析查询
public class FieldInjectQueryParser extends QueryParser { private final String field; public FieldInjectQueryParser(String field, Analyzer analyzer) { super(field, analyzer); this.field = field; } @Override protected Query newTermQuery(Term term) { return super.newTermQuery(createInjectTerm(term)); } @Override protected Query newPrefixQuery(Term prefix) { return super.newPrefixQuery(createInjectTerm(prefix)); } @Override protected Query newRegexpQuery(Term regexp) { return super.newRegexpQuery(createInjectTerm(regexp)); } @Override protected Query newFuzzyQuery(Term term, float minimumSimilarity, int prefixLength) { return super.newFuzzyQuery(createInjectTerm(term), minimumSimilarity, prefixLength); } @Override protected Query newWildcardQuery(Term t) { return super.newWildcardQuery(createInjectTerm(t)); } private Term createInjectTerm(Term term) { return new Term(this.field, term.text()); } }
2条答案
按热度按时间rjzwgtxy1#
如果我没有理解错的话,您需要一个如下的查询
解释为
。
为此,您可以编写一个replacer方法,该方法遍历解析的树,并在到达包含字段名的对象时替换字段(例如Term、PhraseQuery、SpanNearQuery或您拥有的任何对象)。
在Java中,你只能通过反射来改变那些类中对象的字段名,另一个选择是用其他字段名来克隆解析后的树。
您可以编写一个“replacer方法”,它接受一个查询对象,并根据查询类型(例如,布尔查询、短语查询、术语查询等)处理它。
如果你选择克隆的方式,你的方法将返回一个新的对象。
编辑:
下面是一个具有4种查询类型的Java示例代码(不考虑提升):
另一个不那么干净的选择是使用整个查询的toString,替换其中的所有字段,然后再次解析。
mrphzbgm2#
如果将来有人遇到这种情况,一个更干净的解决方案将是创建一个新的查询解析器,并使用该字段重新解析查询