18、学习Lucene3.5索引之自定义评分

/**
 * 自定义评分流程:
 * 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")+"]");
            }
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值