【Lucene3.6.2入门系列】第08节_高级搜索之自定义评分

[java]  view plain copy print ?
  1. package com.jadyer.lucene;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.util.Random;  
  6.   
  7. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  8. import org.apache.lucene.document.Document;  
  9. import org.apache.lucene.document.Field;  
  10. import org.apache.lucene.document.NumericField;  
  11. import org.apache.lucene.index.CorruptIndexException;  
  12. import org.apache.lucene.index.IndexReader;  
  13. import org.apache.lucene.index.IndexWriter;  
  14. import org.apache.lucene.index.IndexWriterConfig;  
  15. import org.apache.lucene.index.Term;  
  16. import org.apache.lucene.search.IndexSearcher;  
  17. import org.apache.lucene.search.Query;  
  18. import org.apache.lucene.search.ScoreDoc;  
  19. import org.apache.lucene.search.TermQuery;  
  20. import org.apache.lucene.search.TopDocs;  
  21. import org.apache.lucene.store.Directory;  
  22. import org.apache.lucene.store.FSDirectory;  
  23. import org.apache.lucene.util.Version;  
  24.   
  25. import com.jadyer.custom.MyNameScoreQuery;  
  26.   
  27. /** 
  28.  * 【Lucene3.6.2入门系列】第08节_高级搜索之自定义评分 
  29.  * @create Aug 19, 2013 12:13:14 PM 
  30.  * @author 玄玉<http://blog.csdn.net/jadyer> 
  31.  */  
  32. public class AdvancedSearchByScore {  
  33.     private Directory directory;  
  34.     private IndexReader reader;  
  35.       
  36.     public AdvancedSearchByScore(){  
  37.         /**文件大小*/  
  38.         int[] sizes = {901020106050};  
  39.         /**文件名*/  
  40.         String[] names = {"Michael.java""Scofield.ini""Tbag.txt""Jack""Jade""Jadyer"};  
  41.         /**文件内容*/  
  42.         String[] contents = {"my java blog is http://blog.csdn.net/jadyer",  
  43.                              "my Java Website is http://www.jadyer.cn",  
  44.                              "my name is jadyer",  
  45.                              "I am a Java Developer",  
  46.                              "I am from Haerbin",  
  47.                              "I like java of Lucene"};  
  48.         IndexWriter writer = null;  
  49.         Document doc = null;  
  50.         try {  
  51.             directory = FSDirectory.open(new File("myExample/01_index/"));  
  52.             writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_36, new StandardAnalyzer(Version.LUCENE_36)));  
  53.             writer.deleteAll();  
  54.             for(int i=0; i<sizes.length; i++){  
  55.                 doc = new Document();  
  56.                 doc.add(new NumericField("size", Field.Store.YES, true).setIntValue(sizes[i]));  
  57.                 doc.add(new Field("name", names[i], Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));  
  58.                 doc.add(new Field("content", contents[i], Field.Store.NO, Field.Index.ANALYZED));  
  59.                 //添加一个评分域,专门在自定义评分时使用  
  60.                 //此时默认为Field.Store.NO和Field.Index.ANALYZED_NO_NORMS  
  61.                 doc.add(new NumericField("fileScore").setIntValue(new Random().nextInt(600)));  
  62.                 writer.addDocument(doc);  
  63.             }  
  64.         } catch (Exception e) {  
  65.             e.printStackTrace();  
  66.         } finally {  
  67.             if(null != writer){  
  68.                 try {  
  69.                     writer.close();  
  70.                 } catch (IOException ce) {  
  71.                     ce.printStackTrace();  
  72.                 }  
  73.             }  
  74.         }  
  75.     }  
  76.       
  77.     /** 
  78.      * 获取IndexReader实例 
  79.      */  
  80.     private IndexReader getIndexReader(){  
  81.         try {  
  82.             if(reader == null){  
  83.                 reader = IndexReader.open(directory);  
  84.             }else{  
  85.                 //if the index was changed since the provided reader was opened, open and return a new reader; else,return null  
  86.                 //如果当前reader在打开期间index发生改变,则打开并返回一个新的IndexReader,否则返回null  
  87.                 IndexReader ir = IndexReader.openIfChanged(reader);  
  88.                 if(ir != null){  
  89.                     reader.close(); //关闭原reader  
  90.                     reader = ir;    //赋予新reader  
  91.                 }  
  92.             }  
  93.             return reader;  
  94.         }catch(Exception e) {  
  95.             e.printStackTrace();  
  96.         }  
  97.         return null//发生异常则返回null  
  98.     }  
  99.       
  100.       
  101.     /** 
  102.      * 自定义评分搜索 
  103.      */  
  104.     public void searchByCustomScoreQuery(){  
  105.         IndexSearcher searcher = new IndexSearcher(this.getIndexReader());  
  106. //      //创建一个评分域  
  107. //      FieldScoreQuery fsq = new FieldScoreQuery("fileScore", FieldScoreQuery.Type.INT);  
  108. //      //创建自定义的CustomScoreQuery对象  
  109. //      Query query = new MyCustomScoreQuery(new TermQuery(new Term("content", "java")), fsq);  
  110.         Query query = new MyNameScoreQuery(new TermQuery(new Term("content""java")));  
  111.         try {  
  112.             TopDocs tds = searcher.search(query, 10);  
  113.             for(ScoreDoc sd : tds.scoreDocs){  
  114.                 Document doc = searcher.doc(sd.doc);  
  115.                 System.out.print("文档编号=" + sd.doc + "  文档权值=" + doc.getBoost() + "  文档评分=" + sd.score + "    ");  
  116.                 System.out.println("size=" + doc.get("size") + "  name=" + doc.get("name"));  
  117.             }  
  118.         } catch (CorruptIndexException e) {  
  119.             e.printStackTrace();  
  120.         } catch (IOException e) {  
  121.             e.printStackTrace();  
  122.         } finally {  
  123.             if(searcher != null){  
  124.                 try {  
  125.                     searcher.close();  
  126.                 } catch (IOException e) {  
  127.                     e.printStackTrace();  
  128.                 }  
  129.             }  
  130.         }  
  131.     }  
  132.       
  133.       
  134.     /** 
  135.      * 测试一下评分效果 
  136.      */  
  137.     public static void main(String[] args) {  
  138.         new AdvancedSearchByScore().searchByCustomScoreQuery();  
  139.     }  
  140. }  


下面是我们自定义的评分类MyCustomScoreQuery.java

[java]  view plain copy print ?
  1. package com.jadyer.custom;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.index.IndexReader;  
  6. import org.apache.lucene.search.Query;  
  7. import org.apache.lucene.search.function.CustomScoreProvider;  
  8. import org.apache.lucene.search.function.CustomScoreQuery;  
  9. import org.apache.lucene.search.function.ValueSourceQuery;  
  10.   
  11. /** 
  12.  * 自定义评分的步骤 
  13.  * @see 1)创建一个类继承于CustomScoreQuery 
  14.  * @see 2)覆盖CustomScoreQuery.getCustomScoreProvider()方法 
  15.  * @see 3)创建一个类继承于CustomScoreProvider 
  16.  * @see 4)覆盖CustomScoreProvider.customScore()方法(我们的自定义评分主要就是在此方法中完成的) 
  17.  * @create Aug 6, 2013 10:30:46 AM 
  18.  * @author 玄玉<http://blog.csdn.net/jadyer> 
  19.  */  
  20. public class MyCustomScoreQuery extends CustomScoreQuery {  
  21.     private static final long serialVersionUID = -2373017691291184609L;  
  22.       
  23.     public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {  
  24.         //ValueSourceQuery参数就是指专门用来做评分的Query,即评分域的FieldScoreQuery  
  25.         super(subQuery, valSrcQuery);  
  26.     }  
  27.       
  28.     @Override  
  29.     protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {  
  30.         //如果直接返回super的,就表示使用原有的评分规则,即通过[原有的评分*传入的评分域所获取的评分]来确定最终评分  
  31.         //return super.getCustomScoreProvider(reader);  
  32.         return new MyCustomScoreProvider(reader);  
  33.     }  
  34.       
  35.       
  36.     private class MyCustomScoreProvider extends CustomScoreProvider {  
  37.         public MyCustomScoreProvider(IndexReader reader) {  
  38.             super(reader);  
  39.         }  
  40.         @Override  
  41.         public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {  
  42.             //subQueryScore--表示默认文档的打分,valSrcScore--表示评分域的打分  
  43.             //该方法的返回值就是文档评分,即ScoreDoc.score获取的结果  
  44.             System.out.println("subQueryScore=" + subQueryScore + "    valSrcScore=" + valSrcScore);  
  45.             return subQueryScore/valSrcScore;  
  46.         }  
  47.     }  
  48. }  

下面是自定义的采用特殊文件名作为评分标准的评分类MyNameScoreQuery.java

[java]  view plain copy print ?
  1. package com.jadyer.custom;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.index.IndexReader;  
  6. import org.apache.lucene.search.FieldCache;  
  7. import org.apache.lucene.search.Query;  
  8. import org.apache.lucene.search.function.CustomScoreProvider;  
  9. import org.apache.lucene.search.function.CustomScoreQuery;  
  10.   
  11. /** 
  12.  * 采用特殊文件名作为评分标准 
  13.  * @create Aug 6, 2013 2:17:13 PM 
  14.  * @author 玄玉<http://blog.csdn.net/jadyer> 
  15.  */  
  16. public class MyNameScoreQuery extends CustomScoreQuery {  
  17.     private static final long serialVersionUID = -2813985445544972520L;  
  18.       
  19.     public MyNameScoreQuery(Query subQuery) {  
  20.         //由于这里是打算根据文件名来自定义评分,所以重写构造方法时不必传入评分域的ValueSourceQuery  
  21.         super(subQuery);  
  22.     }  
  23.       
  24.     @Override  
  25.     protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {  
  26.         return new FilenameScoreProvider(reader);  
  27.     }  
  28.       
  29.       
  30.     private class FilenameScoreProvider extends CustomScoreProvider {  
  31.         String[] filenames;  
  32.         public FilenameScoreProvider(IndexReader reader) {  
  33.             super(reader);  
  34.             try {  
  35.                 //在IndexReader没有关闭之前,所有的数据都会存储到一个预缓存中(缺点是占用大量内存)  
  36.                 //所以我们可以通过预缓存获取name域的值(获取到的是name域所有值,故使用数组)  
  37.                 this.filenames = FieldCache.DEFAULT.getStrings(reader, "name");  
  38.             } catch (IOException e) {  
  39.                 e.printStackTrace();  
  40.             }  
  41.         }  
  42.         @Override  
  43.         public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {  
  44.             //由于FilenameScoreQuery构造方法没有传入ValueSourceQuery,故此处ValueSourceQuery默认为1.0  
  45.             System.out.println("subQueryScore=" + subQueryScore + "    valSrcScore=" + valSrcScore);  
  46.             if(filenames[doc].endsWith(".java") || filenames[doc].endsWith(".ini")){  
  47.                 //只加大java文件和ini文件的评分  
  48.                 return subQueryScore*1.5f;  
  49.             }else{  
  50.                 return subQueryScore/1.5f;  
  51.             }  
  52.         }  
  53.     }  
  54. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值