我想怎么可能。假设我正在搜索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);
答案 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 异常,而不是需要一个变通方法,增加此数字或重写此查询不同。