这里我们是工程lucene_analyzer04
- 1.自定义评分思路
- 创建一个类继承于
CustomScoreQuery
- 覆盖里面的方法
getCustomScoreProvider()
- 创建一个类
CustomScoreProvider
- 覆盖
CustomScoreProvider中的方法customScore()
,在这个方法中创建评分规则。
- 创建一个类继承于
- 2.首先看一个示例
我们在FileIndexUtil.java
中定义一个随机数,这个随机数作为一个评分。
// 创建索引
public static void index(boolean hasNew) {
IndexWriter writer = null;
try {
writer = new IndexWriter(directory, new IndexWriterConfig(
Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
if (hasNew) {
writer.deleteAll();//如果我们要新建索引,那么将之前创建的删除
}
File file = new File("E:/myeclipse/Lucene/somefile");
Document document = null;
Random random = new Random();
for (File f : file.listFiles()) {
//将每个索引的评分设置成一个随机数
int score = random.nextInt(600);
document = new Document();
document.add(new Field("content", new FileReader(f)));
document.add(new Field("filename", f.getName(),
Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("path", f.getAbsolutePath(),
Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new NumericField("date", Field.Store.YES, true)
.setLongValue(f.lastModified()));
// 最后我们将字节数转换成kb
document.add(new NumericField("size", Field.Store.YES, true)
.setIntValue((int) (f.length())));
//这里我们使用score评分来创建索引,没有存储,搜索出来的时候为null
//这里我自己随机设置的一个评分
document.add(new NumericField("score", Field.Store.NO, true).setIntValue(score));
writer.addDocument(document);
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
说明:定义随机评分之后再次生成索引。
- 3.自定义评分规则
MyScoreQuery.java
public void searchByScoreQuery(){
try {
IndexSearcher searcher = new IndexSearcher(IndexReader.open(FileIndexUtil.getDirectory()));
Query q = new TermQuery(new Term("content", "json"));
//1、创建一个评分域
FieldScoreQuery fsq = new FieldScoreQuery("score", Type.INT);//如果是字符串选择BYTE类型,这里是int类型
//2、根据评分域和原有的Query创建自定义的Query对象
MyCustomScoreQuery query = new MyCustomScoreQuery(q, fsq);
TopDocs tds = null;
tds = searcher.search(query, 20);//使用自定义的query
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (ScoreDoc sd : tds.scoreDocs) {
Document doc = searcher.doc(sd.doc);
System.out.println("id:" + sd.doc + ",评分:" + sd.score
+ ",名称:" + doc.get("filename") + ",路径:" + doc.get("path")
+ ",文件大小:" + doc.get("size") + ",日期:"
+ sdf.format(new Date(Long.valueOf(doc.get("date")))));
}
searcher.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private class MyCustomScoreQuery extends CustomScoreQuery{
//subQuery表示原有的Query,valSrcQuery用于做评分的Query
//CustomScoreQuery其实有很多构造方法,我们可以一次性传入很多评分规则
public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {
super(subQuery, valSrcQuery);
}
//3、覆盖此方法
@Override
protected CustomScoreProvider getCustomScoreProvider(IndexReader reader)
throws IOException {
//默认情况实现的评分是通过 原有的评分*传入 进来的评分域得到最后的评分
//而这种评分算法很显然是满足不了我们的要求的,于是我们自己为了根据不同的需求需要
//自己进行评分设定
/*
* 自定义评分的步骤
* (1)创建一个类继承于CustomScoreProvider
* (2)覆盖CustomScoreProvider中的方法customScore()
* */
return new MyCustomScoreProvider(reader);
}
}
private class MyCustomScoreProvider extends CustomScoreProvider{
public MyCustomScoreProvider(IndexReader reader) {
super(reader);
}
//此方法中subQueryScore表示默认文档的打分,valSrcScore表示的是评分域的打分
@Override
public float customScore(int doc, float subQueryScore, float valSrcScore)
throws IOException {
//这是按评分的降序排,之前默认的是subQueryScore * valSrcScore
return subQueryScore / valSrcScore;
}
}
说明:
- 1.这里我们是利用之前创建的那个随机评分,首先当然是创建评分域
FieldScoreQuery
,这里我们选择的是score
域。然后是根据评分域和原有的Query
创建自定义的Query
对象。
自定义的Query
对象MyCustomScoreQuery
必须继承CustomScoreQuery
对象,然后需要一个构造方法,同时覆写getCustomScoreProvider
方法,当然此方法中我们需要自定义评分规则类MyCustomScoreProvider
,此类需要继承CustomScoreProvider
,也是需要一个构造方法,同时覆写customScore
方法,而我们真正的自定义评分规则就在这个方法中定义。