强制lucene使用与解析查询中指定的字段不同的字段

mlnl4t2r  于 2022-11-07  发布在  Lucene
关注(0)|答案(2)|浏览(209)

我正在使用Lucene.Net3.0.3,需要在一个特定的字段中进行搜索(忽略查询中指定的任何字段)。我得到了一个经过解析的Lucene查询,所以我无法生成一个带有所需字段的经过解析的查询。
Lucene中是否有任何功能可以让我循环查询的术语并更改字段?给定的查询将是一个复杂的查询,其中将有跨度,子句等。
或者,可能有某种方法强制Lucene忽略解析查询中给出的字段,只使用指定的字段。

rjzwgtxy

rjzwgtxy1#

如果我没有理解错的话,您需要一个如下的查询

+body:hello +(+body:test -header:xy)

解释为

+body:hello +(body:test -body:xy)


为此,您可以编写一个replacer方法,该方法遍历解析的树,并在到达包含字段名的对象时替换字段(例如Term、PhraseQuery、SpanNearQuery或您拥有的任何对象)。
在Java中,你只能通过反射来改变那些类中对象的字段名,另一个选择是用其他字段名来克隆解析后的树。
您可以编写一个“replacer方法”,它接受一个查询对象,并根据查询类型(例如,布尔查询、短语查询、术语查询等)处理它。

  • 在布尔查询的情况下,您可以遍历子句,并将子查询递归地委托给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,替换其中的所有字段,然后再次解析。

mrphzbgm

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());
    }
}

相关问题