Lucene笔记24-Lucene的使用-自定义评分简介

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36059561/article/details/83479624

一、自定义评分流程

有时候,Lucene提供的计算评分规则可能不符合业务需求,所以我们需要自定义评分规则,来实现自定义评分。自定义评分的流程:创建一个类继承CustomScoreQuery、重写getCustomScoreProvider()方法、创建CustomScoreProvider类、重写customScore()方法。

二、代码实现

package com.wsy;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
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.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;

public class MyScoreQuery {
    private static Directory directory;
    private static IndexReader indexReader;

    static {
        try {
            directory = FSDirectory.open(new File("E:\\Lucene\\IndexLibrary"));
            indexReader = IndexReader.open(directory);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void index(boolean update) {
        IndexWriter indexWriter = null;
        try {
            indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
            if (update) {
                indexWriter.deleteAll();
            }
            File[] files = new File("E:\\Lucene\\SearchSource").listFiles();
            Random random = new Random();
            for (File file : files) {
                int score = random.nextInt(100);
                Document document = new Document();
                document.add(new Field("content", new FileReader(file)));
                document.add(new Field("fileName", file.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                document.add(new Field("path", file.getAbsolutePath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                document.add(new NumericField("date", Field.Store.YES, true).setLongValue(file.lastModified()));
                document.add(new NumericField("size", Field.Store.YES, true).setIntValue((int) (file.length())));
                document.add(new NumericField("score", Field.Store.YES, true).setIntValue(score));
                indexWriter.addDocument(document);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (indexWriter != null) {
                try {
                    indexWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void searchByScoreQuery() {
        try {
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
            Query query = new TermQuery(new Term("content", "java"));
            // 创建一个评分域
            FieldScoreQuery fieldScoreQuery = new FieldScoreQuery("score", FieldScoreQuery.Type.INT);
            // 根据评分域和原有的Query创建自定义的Query对象
            MyCustomScoreQuery myCustomScoreQuery = new MyCustomScoreQuery(query, fieldScoreQuery);
            TopDocs topDocs = indexSearcher.search(myCustomScoreQuery, 100);
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
                Document document = indexSearcher.doc(scoreDoc.doc);
                System.out.println(scoreDoc.doc + "-->" + scoreDoc.score + "-->" + document.get("fileName") + "-->" + document.get("score") + "-->" + document.get("size"));
            }
            indexSearcher.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class MyCustomScoreQuery extends CustomScoreQuery {
        // subQuery表示原有query,valSrcQueries表示自定义评分的query
        public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQueries) {
            super(subQuery, valSrcQueries);
        }

        @Override
        protected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {
            // 默认情况实现的评分是通过原有评分*传进来的评分域所获取的评分确定的
            // return super.getCustomScoreProvider(reader);
            // 为了根据不用的需求进行评分,需要自己进行评分设定
            return new MyCustomScoreProvider(indexReader);
        }
    }

    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 {
            // return super.customScore(doc, subQueryScore, valSrcScore);
            // 在这里进行评分的修改操作
            return subQueryScore / valSrcScore;
        }
    }

    public static void main(String[] args) {
        MyScoreQuery myScoreQuery = new MyScoreQuery();
        myScoreQuery.index(true);
        myScoreQuery.searchByScoreQuery();
    }
}

原来的评分是subQueryScore * valSrcScore来完成的,为了演示效果,我们将customScore()方法的返回值改为subQueryScore / valSrcScore,再次查看结果,发现和刚才的默认评分显示的评分已经不一样了。这里先大致了解一下怎么去通过重写getCustomScoreProvider()方法和customScore()方法来实现自定义分数,下一节我们将学习根据域进行评分设定。

猜你喜欢

转载自blog.csdn.net/qq_36059561/article/details/83479624