Lucene的自定义评分

来源:互联网 发布:知网查重 知乎 编辑:程序博客网 时间:2024/06/09 19:47

使用Lucene进行查询时,默认是按评分由高到低进行排序的。

而这里的评分是从哪里来的呢?原来Lucene本身就会根据关键词出现的频率等计算出一个评分,我们称之为原始评分。

这个原始评分往往不能满足我们实际的需求。需要我们自定义评分规则。


Lucene可以将原始的Query对象跟org.apache.lucene.search.function.FieldScoreQuery的对象作为参数传入到org.apache.lucene.search.function包中的CustomScoreQuery类的构造函数,得出一个CustomScoreQuery的对象。

public void searchByScoreQuery() {try {IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory()));Query q = new TermQuery(new Term("content","java"));//创建一个评分域查询对象FieldScoreQuery fd = new FieldScoreQuery("score",Type.INT);//将原始的查询对象跟评分域查询对象传入自定义评分对象的构造函数,得到一个自定义评分对象MyCustomScoreQuery query = new MyCustomScoreQuery(q,fd);TopDocs tds = null;tds = searcher.search(query, 100);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");for(ScoreDoc sd:tds.scoreDocs) {Document d = searcher.doc(sd.doc);System.out.println(sd.doc+":("+sd.score+")" +"["+d.get("filename")+"��"+d.get("path")+"��--->"+d.get("size")+"-----"+sdf.format(new Date(Long.valueOf(d.get("date"))))+"]");}searcher.close();} catch (CorruptIndexException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}


那在Lucene中,如何编写自己的评分规则呢?

1.创建一个类MyCustomScoreQuery继承CustomScoreQuery,覆盖其getCustomScoreProvider方法;

 

@SuppressWarnings("serial")private class MyCustomScoreQuery extends CustomScoreQuery {public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {super(subQuery, valSrcQuery);}@Overrideprotected CustomScoreProvider getCustomScoreProvider(IndexReader reader)throws IOException {//默认情况实现的评分是通过原有的评分*传入进来的评分域所获取的评分来确定最终评分的//为了根据不同的需求进行评分,需要自己进行评分的设定/** * 自定义评分的步骤 * 创建一个类继承于CustomScoreProvider * 覆盖其customScore方法 */return new MyCustomScoreProvider(reader);}}

2.创建一个类MyCustomScoreProvider继承CustomScoreProvider,覆盖其customScore方法;

这两步的关联就是,将MyCustomScoreProvider作为MyCustomScoreQuery类中的getCustomScoreProvider方法的返回值。

private class MyCustomScoreProvider extends CustomScoreProvider {public MyCustomScoreProvider(IndexReader reader) {super(reader);}/** * subQueryScore 原有的评分 * valSrcScore 评分域的分值 */@Overridepublic float customScore(int doc, float subQueryScore, float valSrcScore)throws IOException {return subQueryScore/valSrcScore;}}


而自己的评分规则是在MyCustomScoreProvider类中的customScore方法体内进行定义的。如果需要用到文档中某个域的值,可以用域缓存获取。FieldCache.DEFAULT.getStrings

private class FilenameScoreProvider extends CustomScoreProvider {String[] filenames = null;public FilenameScoreProvider(IndexReader reader) {super(reader);try {filenames = FieldCache.DEFAULT.getStrings(reader, "filename");} catch (IOException e) {e.printStackTrace();}}@Overridepublic float customScore(int doc, float subQueryScore, float valSrcScore)throws IOException {//如何根据doc获取响应的field值/* * 在reader没有关闭之前,所有的数据会存储在一个域缓存中,可以域缓存获取很多有用的信息 * filenames = FieldCache.DEFAULT.getStrings(reader, "filename");可以获取所有的fieldname域的信息 */String filename = filenames[doc];if(filename.endsWith(".txt")||filename.endsWith(".ini")) {return subQueryScore*1.5f;}return subQueryScore/1.5f;}}



 

 

 

 

 

 

 

 

 


原创粉丝点击