lucene自定义评分域

来源:互联网 发布:淘宝客骗局揭秘 编辑:程序博客网 时间:2024/05/19 03:28

搜索查询业务场景:

1:搜索一组数据,这些数据录入时间在3个月之内;提高权重。1年以内,权重不变;1年以前,降低查询权重;

2:如果 是vip客户,提高该用户下所在查询文档权重(类似百度的竞价排名);


分析:有两种思路

第一种方式:在构建索引的时候,根据业务,去构建索引,如下:

Document document = new Document();
switch (vip)
{
   case VIP.Gold: document.SetBoost(2F); break;
   case VIP.Argentine: document.SetBoost(1.5F); break;
}

本人极其不推荐这种方式,有两个缺陷:

                 1:灵活性不高,夹杂着各种业务方法,去创建索引。显得太笨重,维护成本太高;

                 2:这种直接通过doc.SetBoost() 方法直接提高权重在较新的lucene版本中已经废弃了。老的版本中还能看到这个方法;


第二种方式:在查询的时候去做处理。这种方式更加的灵活。这种方式就是这篇文章的所要概述的内容---自定义评分

简单介绍下步骤

新建一个类去实现CustomScoreQuery这个类,重写getCustomScoreProvider(获取自定义评分规则)方法,然后再创建一个类继承CustomScoreProvider类。覆盖CustomScoreProvider 中的customScore,通过customScore这个方法去控制最终评分信息;

代码:

<span style="font-size:14px;">import java.io.IOException;import org.apache.lucene.document.Document;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.Term;import org.apache.lucene.search.FieldCache;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TermQuery;import org.apache.lucene.search.TopDocs;import org.apache.lucene.search.function.CustomScoreProvider;import org.apache.lucene.search.function.CustomScoreQuery;import org.apache.lucene.search.function.FieldScoreQuery;import org.apache.lucene.search.function.ValueSourceQuery;import org.apache.lucene.search.function.FieldScoreQuery.Type;public class FtsCustomQuery { public static void main(String[] args) {new FtsCustomQuery().customFtsScore();}/** *  */public void customFtsScore(){try{IndexSearcher searcher=new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory()));Query q=new TermQuery(new Term("content","java"));//创建一个评分域FieldScoreQuery fsq=new FieldScoreQuery("score", Type.INT);//根据评分域和原来的query创建自己定义的评分域FtsCustomScore query=new FtsCustomScore(q,fsq);TopDocs tds = searcher.search(query, 100);for(ScoreDoc sd:tds.scoreDocs) {Document d = searcher.doc(sd.doc);//System.out.println(searcher.explain(query, sd.doc));System.out.println(sd.doc+":("+sd.score+")" +"["+d.get("filename")+"【"+d.get("path")+"】--->"+d.get("size")+"-----"+d.get("score")+"]");}searcher.close();}catch (Exception e) {}}/** * 自定义评分步骤 * @author hhc * */@SuppressWarnings("serial")private class FtsCustomScore extends CustomScoreQuery{public FtsCustomScore(Query subQuery, ValueSourceQuery valSrcQuery) {super(subQuery, valSrcQuery);}@Overrideprotected CustomScoreProvider getCustomScoreProvider(IndexReader reader)throws IOException {//默认情况实现的评分是通过原有的评分*传入进来的评分域    ===最终评分/** * 为了应对不同的评分需求,必须要自己设定评分规则 * 自定义规则步骤 * 创建一个类继承CustomScoreProvider类 * 覆盖CustomScoreQuery中的getCustomScoreProvider方法 */return new FtsCustomScoreProvide(reader);//return super.getCustomScoreProvider(reader);//源码// protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {    //   return new CustomScoreProvider(reader);  //}}}/** * 重写自定义评分规则类 * 重写CustomScoreProvider 中的customScore * @author hhc * */private class FtsCustomScoreProvide extends CustomScoreProvider{/** * 在reader没有关闭之前,所有的数据会存储到一个域缓存中 * String[] path = FieldCache.DEFAULT.getStrings(reader, "path"); * @param reader */public FtsCustomScoreProvide(IndexReader reader) {super(reader);try {String[] path = FieldCache.DEFAULT.getStrings(reader, "path");System.out.println(path.length);for(String p:path){System.out.println(p);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/** * subQueryScore:默认文档的打分 * valSrcScore:评分域的打分 *  * 自定义评分,就是通过算法,对这个customScore方法中的subQueryScore,valSrcScore的值进行业务计算 */@Overridepublic float customScore(int doc, float subQueryScore, float valSrcScore)throws IOException {// TODO Auto-generated method stubreturn subQueryScore/valSrcScore;//可以通过doc获取查询出来的文档。。然后根据业务需求去 控制分值/** * 比如淘宝网上,搜索某物品,入库时间 我要控制在3年之内的 * 就可以通过查询出来的文档,在这里写定义他的评分 */}//源码CustomScoreProvider中customScore 计算评分规则 ;subQueryScore * valSrcScore;//  public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {//    return subQueryScore * valSrcScore;//  }}}</span>



1 0