前记
这段时间需要修改一个别人写的一个搜索有关的项目,恰好底层使用的是lucene搜索框架。
为什么要去修改呢,当然是搜索结果不太令人满意啦,于是去研读了项目中关于搜索的代码。。。。。。
正文
经过了几天代码的研读,最终总结出来了几条问题:
创建索引的过程,相当简单,感觉仅仅是把lucene当成关键词匹配的工具去了(需要修改索引策略)
搜索的过程也是比较简单,没有结合项目的需求,定制化搜索(搜索策略需要修改)
额,感觉上面两条好像是在说废话,感觉lucene的和核心就是索引和搜索
为了能尽快解决问题,初步修改就定为了:
索引阶段,将信息分成多个域,同时根据域的重要程度,加入权重。还有就是加入搜索结果排序要使用的字段(分域,权重,加入排序字段)
搜索阶段 根据类别搜索不同的域,同时加入自定义评分
下面就简单的说一下自定义评分:
我用的是lucene是:
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>4.10.2</version>
</dependency>
上网查了很多的资料,发现lucene实现自定义评分是通过在构建查询的时候加入的,操作起来很方便。直接上代码吧:
public class MyCustomScoreQuery extends CustomScoreQuery {
public MyCustomScoreQuery(Query subQuery) {
super(subQuery);
}
@Override
protected CustomScoreProvider getCustomScoreProvider(
AtomicReaderContext context) throws IOException {
/**
* 自定义的评分provider
* **/
return new AbilityCoverageScoreProvider(context);
}
private class MyCustomScoreProvider extends CustomScoreProvider {
private AtomicReaderContext context = null;
public MyCustomScoreProvider(AtomicReaderContext context) {
super(context);
this.context = context;
}
@Override
public float customScore(int doc, float subQueryScore, float valSrcScore)
throws IOException {
//获取double型,使用Cache获取更加的快速
FieldCache.Doubles doubles = FieldCache.DEFAULT.getDoubles(context.reader(), "range", false);
double range= doubles.get(doc);
return subQueryScore + range;
}
}
}
总结下来就是:
继承CustomScoreQuery类,覆盖getCustomScoreProvider(AtomicReaderContext context)方法,返回自己的评分对象
继承CustomScoreProvider,覆盖customScore(int doc, float subQueryScore, float valSrcScore)方法,返回评分结果
自定义评分逻辑就是写在customScore(int doc, float subQueryScore, float valSrcScore)里面,事先算好的排序因子,可以当成是域放在document里面,然后在自定义评分的时候取出来,实现自定义评分从而影响排序。
最后就只用使用自己的MyCustomScoreQuery去包装一个query,然后去搜索就行了。
Query query = 生成好的query
Query customQuery = new MyCustomScoreQuery(query);
最后用customQuery去搜索。。。