/**
* 自定义评分流程:
* 1.创建一个评分域
* 2.根据原有Query(termQuery)和评分域Query(scoreQuery)创建自定义的MyCustomScoreQuery对象
* 2.1创建自定义的MyCustomScoreQuery对象
* 2.2重载“getCustomScoreProvider()”方法
* 3.自定义评分步骤:
* 3.1自定义类继承自CustomScoreProvider
* 3.2重载customScore()方法
*/
public class MyScoreQuery {
public void searchByScoreQuery(){
IndexSearcher indexSearcher = null;
try {
indexSearcher = new IndexSearcher(IndexReader.open(FileIndexUtil.getDirectory()));
TermQuery termQuery = new TermQuery(new Term("filename", "公主"));
//1.创建一个评分域
/**
* 创建一个评分域:FieldScoreQuery
* FieldScoreQuery(String field, Type type)
* 参数一:域名
* 参数二:type 类型
* FieldScoreQuery.Type.INT 域值是整型
* FieldScoreQuery.Type.BYTE 域值是字符串
*/
FieldScoreQuery scoreQuery = new FieldScoreQuery("score", FieldScoreQuery.Type.INT);
//2.根据原有Query(termQuery)和评分域Query(scoreQuery)创建自定义的MyCustomScoreQuery对象
MyCustomScoreQuery myCustomScoreQuery = new MyCustomScoreQuery(termQuery, scoreQuery);
searchByQuery(indexSearcher, myCustomScoreQuery);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (indexSearcher != null){
try {
indexSearcher.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 2.1创建自定义类继承自“CustomScoreQuery”
*/
private class MyCustomScoreQuery extends CustomScoreQuery{
/**
* 自定义类继承CustomScoreQuery,需要添加构造函数,共有三种:
* 第一种:CustomScoreQuery(Query subQuery)
* 第一种只传入“原有Query”,即默认评分规则
* 第二种:CustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery)
* 第二种传入“原有Query”和“自定义的评分域Query”,即加入自定义评分规则
* 第三种:CustomScoreQuery(Query subQuery, ValueSourceQuery... valSrcQueries)
* 第二种传入“原有Query”和多个“自定义的评分域Query”,即加入多个自定义评分规则
* 可以实现:
* 搜索文件标题含有“公主”的文件,同时按照文件修改时间由近到远的排序,同时按照
* 文件大小由小到大排序
*/
/**
* @param subQuery 原有Query(termQuery)
* @param valSrcQuery 评分域Query(scoreQuery)
*/
public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {
super(subQuery, valSrcQuery);
}
/**
* 2.2重载“getCustomScoreProvider()”方法
* 其中,super.getCustomScoreProvider(reader)是默认评分规则,即:
* 原有评分*传进来的评分域
* 为根据不同的需求进行评分,需要自己进行评分的设定,即自定义类继承CustomScoreProvider
*/
@Override
protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
// return new MyCustomScoreProvider(reader);
return new FileNameCustomScoreProvider(reader);
}
}
/**
* 3.自定义评分步骤:
* 3.1自定义类继承自CustomScoreProvider
* 3.2重载customScore()方法
*/
/**
* 3.1自定义类继承自CustomScoreProvider
*/
private class MyCustomScoreProvider extends CustomScoreProvider{
public MyCustomScoreProvider(IndexReader reader) {
super(reader);
}
//3.2重载customScore()方法
/**
* 若只传入一个评分域,则需要重载customScore(int doc, float subQueryScore, float valSrcScore)方法
* 若传入多个评分域,则需要重载customScore(int doc, float subQueryScore, float[] valSrcScore)方法
* 参数subQueryScore:默认文档评分
* 参数valSrcScore: 传入评分域评分
*/
@Override
public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
return subQueryScore/valSrcScore;
}
}
/**
* 练习:对原有搜索出来的排序结果再进行优化,“.txt”和“.ini文件在前”,其他按照原有的排序
*/
private class FileNameCustomScoreProvider extends CustomScoreProvider{
String[] fileNames = null;
public FileNameCustomScoreProvider(IndexReader reader) {
super(reader);
try {
/**
* 在IndexReader没有关闭之前,所有的数据都会存储在一个缓存域中,可以通过缓存域获取域值(前提是该域存储起来了)
* FieldCache.DEFAULT.getStrings(reader, "filename")
*/
fileNames = FieldCache.DEFAULT.getStrings(reader, "filename");
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
/**
* 如何通过doc获取相应的filed值?
* 在IndexReader没有关闭之前,所有的数据都会存储在一个缓存域中,可以通过缓存域获取域值(前提是该域存储起来了)
* FieldCache.DEFAULT.getStrings(reader, "filename")
*/
String fileName = fileNames[doc];
//文件名被我分词了,找不到了
if (fileName != null && (fileName.endsWith(".txt") || fileName.endsWith(".ini"))){
//若文件是".txt"或".ini"文件,加评分
return subQueryScore*valSrcScore*10;
}
return subQueryScore*valSrcScore;
}
}
public void searchByQuery(IndexSearcher indexSearcher, Query termQuery) throws IOException {
TopDocs topDocs = indexSearcher.search(termQuery, 100);
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
if (!CollectionUtil.isEmpty(scoreDocs)){
for (ScoreDoc scoreDoc:scoreDocs){
Document document = indexSearcher.doc(scoreDoc.doc);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
System.out.println(scoreDoc.doc+"["+scoreDoc.score+"]---->["+
"["+document.get("filename")+"]---->["
+simpleDateFormat.format(new Date(Long.valueOf(document.get("time"))))+"]---->["
+document.get("size")+"]");
}
}
}
}