如何在lucene中的文本开头找到匹配时提升文档

时间:2017-01-04 10:07:57

标签: java android lucene

我想怎么可能。假设我正在搜索ka,那么Karthik应该得分高于Aakash。如何提升那些文件?  我已经尝试了this

我正在尝试使用SpanFirstQuery,如下所示。但它不起作用。我正在使用lucene 4.0

//queryString is searchText. e.g ka
//NAME, ORGANIZATION_NAME and ORGANIZATION_POSITION are indexed field names.
Map<String, Analyzer> searchAnalyzers = new HashMap<String, Analyzer>();
searchAnalyzers.put(NAME, new KeywordAnalyzer());
searchAnalyzers.put(ORGANIZATION_NAME, new KeywordAnalyzer());
searchAnalyzers.put(ORGANIZATION_POSITION, new KeywordAnalyzer());
PerFieldAnalyzerWrapper perFieldAnalyzerWrapper = new  PerFieldAnalyzerWrapper(new KeywordAnalyzer(), searchAnalyzers);
MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(Version.LUCENE_40, mSearchFields, perFieldAnalyzerWrapper); //mSearchFiels is array of fiels
multiFieldQueryParser.setDefaultOperator(QueryParser.Operator.AND);
Query query = (Utils.isEmpty(queryString)) ? new MatchAllDocsQuery() : multiFieldQueryParser.parse(QueryParser.escape(queryString)); //queryString is text to be searched

Term term = new Term(NAME, queryString);
SpanFirstQuery spanFirstQuery = new SpanFirstQuery(new SpanTermQuery(term), 5);
spanFirstQuery.setBoost(5.0f);
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(spanFirstQuery, BooleanClause.Occur.SHOULD);
booleanQuery.add(query, BooleanClause.Occur.MUST);
indexSearcher.search(booleanQuery, 100);

1 个答案:

答案 0 :(得分:0)

我的想法,为什么 SpanFirstQuery 是一个坏主意 - 它看起来很像一种解决方法,可能效果不佳(另外,我也不知道如何让它工作起初在性能方面,还需要你存储位置(额外的空间),这是非常需要的。

建议的解决方案:

警告 - 这是实验性的,可能不是生产就绪的解决方案,仍然需要做一些工作。

我使用 WildcardQuery 作为此功能的基础,因为它支持*ka*之类的查询,这就是您想要的。第二个问题 - 评分,因为 WildcardQuery MultiTermQuery 的子类,您可以指定自定义重写方法:

public class BoostPrefixScoringRewrite extends ScoringRewrite<BooleanQuery.Builder> {

    private final String text;

    public BoostPrefixScoringRewrite(String text) {
        // todo should be handled more carefully, since wildcard query supports other than * symbols
        this.text = text.replace("*", "");
    }

    @Override
    protected BooleanQuery.Builder getTopLevelBuilder() {
        BooleanQuery.Builder builder = new BooleanQuery.Builder();
        builder.setDisableCoord(true);
        return builder;
    }

    protected Query build(BooleanQuery.Builder builder) {
        return builder.build();
    }

    @Override
    protected void addClause(BooleanQuery.Builder topLevel, Term term, int docCount,
                             float boost, TermContext states) {
        final TermQuery tq = new TermQuery(term, states);
        if (term.text().startsWith(this.text)) {
            // experiment with the boost value
            topLevel.add(new BoostQuery(tq, 100f), BooleanClause.Occur.SHOULD);
        } else {
            topLevel.add(new BoostQuery(tq, boost), BooleanClause.Occur.SHOULD);
        }

    }

    @Override
    protected void checkMaxClauseCount(int count) {
        if (count > BooleanQuery.getMaxClauseCount())
            throw new BooleanQuery.TooManyClauses();
    }
}

注意提升价值,现在它被硬编码为100,这应该足以始终将以搜索文字开头的字词放在最上面。另外,要看一下 - 如果您的术语列表很宽,使用布尔重写,您可能会遇到 TooManyClauses 异常,而不是需要一个变通方法,增加此数字或重写此查询不同。

如需完整测试,请查看此处 - https://raw.githubusercontent.com/MysterionRise/information-retrieval-adventure/master/lucene5/src/main/java/org/mystic/BoostBeginningWithTest.java