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

时间:2013-07-06 11:57:51

标签: lucene lucene.net

我正在使用Lucene.Net 3.0.3并需要在特定字段中搜索(忽略查询中指定的任何字段)。我得到一个解析的Lucene查询,所以我无法使用我的必填字段生成一个已解析的查询。

Lucene中是否有任何功能允许我循环查询条款并更改字段?给定的查询将是一个复杂的查询,其中有跨度,子句等。

或许有一些方法可以强制Lucene忽略解析查询中给出的字段并仅使用指定的字段。

2 个答案:

答案 0 :(得分:0)

如果我理解正确,您需要像

这样的查询
+body:hello +(+body:test -header:xy)

解释为

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

有关这一点,可以写横穿通过解析树并替换字段到达含有字段名称(例如期限,PhraseQuery,SpanNearQuery或任何你有)的对象时,一个替换器方法。

在Java中,您只能通过反射从这些类中更改对象的字段名称。另一种选择是使用其他字段名称克隆已解析的树。

您可以编写一个“替换方法”,它接受查询对象并根据查询类型处理它(即布尔查询,短语查询,术语查询......)。

  • 如果是布尔查询,您可以通过子句进行迭代,并将子查询递归地委托给replacer方法。
  • 如果是术语查询,您可以替换术语中的字段。
  • 如果是短语查询,您可以替换查询中的字段。
  • 等......

如果您选择克隆方式,您的方法将返回一个新对象。

编辑:

以下是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并替换其中的所有字段并再次解析它。

答案 1 :(得分:0)

如果将来有人遇到这种情况,一个更简洁的解决方案是创建一个新的查询解析器并使用字段重新解析查询

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