Lucene查询数据的相关度排序问题

Lucene查询出来的数据排序有两个方面会影响到,
一是tf(Term frequency), 查询的关键字在当前文档中出现 的次数越多,权重越高,排名越靠前
二是df(Document frequency),查询的关键字在多个文档中出现的资料越多,权重相对较低。

那么查询出来的数据是否可以人为影响排序呢? 答案是可以的,总共有两种方式。
一是在创建索引时,设置boost参数:

/**
     * 创建索引时,对指定数据设置影响排序的参数
     * @创建时间:2017年10月8日16:17:21
     */
    @Test
    public void zfIndex() throws IOException{
        //创建写入流,并指定分词器、索引目录
        Directory directory = FSDirectory.open(new File("D:"+File.separator+"lucene_index"+File.separator));
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, new StandardAnalyzer());
        IndexWriter writer = new IndexWriter(directory, config);

        //从数据库获取数据
        BookDao dao = new BookDaoImpl();
        List<Book> books = dao.queryBooks();

        //创建集合中,用以保存要存储到索引文档中的内容
        List<Document> documents = new ArrayList<>();
        Document document ;

        for(Book book : books){
            document = new Document();
            //创建索引域及相关内容
            Field id = new StringField("id", book.getId().toString(), Store.YES);
            Field name = new TextField("name", book.getName(), Store.YES);
            Field price = new FloatField("price", book.getPrice(), Store.YES);
            Field pic = new StringField("pric", book.getPic(), Store.YES);
            Field description = new TextField("description", book.getDescription(),Store.YES);

            //设置boost参数,会影响到它的排序,但注意,在TextField上可以设置boost,StringField、StoreField上不能设置 
            if(book.getId() == 5){
                description.setBoost(100f);
            }
            //创建一个document文档内容
            document.add(id);
            document.add(name);
            document.add(price);
            document.add(pic);
            document.add(description);
            //将当前文档内容写入到集合中
            documents.add(document);
        }
        //将集合中的数据写入索引文件
        for(Document doc : documents){
            writer.addDocument(doc);
        }

        //关闭流
        writer.close();
    }

第二种是在查询时设置参数,只在MultiFieldQueryParser 对象中生效

/**
     * 查询lucene索引数据 @创建时间:2017年10月7日22:57:00
     */
    public void query(Query query) {
        try {
            // 指定查询的索引目录
            Directory directory = FSDirectory.open(new File("D:" + File.separator + "lucene_index" + File.separator));
            // 创建流对象
            IndexReader reader = DirectoryReader.open(directory);
            // 通过流对象创建索引搜索对象
            IndexSearcher searcher = new IndexSearcher(reader);
            // 将查询到的指定索引域数据赋值给TopDocs
            TopDocs topDocs = searcher.search(query, 10);
            // 根据获取查询到的总数据
            int totalHits = topDocs.totalHits;
            // 输出
            System.out.println("共查询到数据总数为:" + totalHits);
            System.out.println();
            // 将查询到的索引数据赋值给数组
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            // 如果未查询到数据,则输出提示
            if (scoreDocs == null || scoreDocs.length == 0) {
                System.out.println("未查询到数据");
            } else {
                // 如果查询到的有数据。则循环输出
                for (ScoreDoc doc : scoreDocs) {
                    // 获取索引ID
                    int docID = doc.doc;
                    // 根据索引数据查询文档中对应的数据
                    Document document = searcher.doc(docID);

                    // 将查询到的数据输出
                    System.out.println("ID:" + document.get("id"));
                    System.out.println("name:" + document.get("name"));
                    System.out.println("price:" + document.get("price"));
                    System.out.println("pic:" + document.get("pic"));
                    System.out.println("description:" + document.get("description"));
                    System.out.println("==================================");
                    System.out.println();
                    System.out.println();
                }

            }
            // 关闭流
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



/**
     * 要查询时,使用Map<String, Float> boosts  设置查询结
     * 果的排序
     * 只有在MultiFieldQueryParser 中才可以使用
     * @创建时间:2017年10月8日16:27:42
     */
    @Test
    public void testSeracher() throws ParseException{
        //查询的多个索引域名称 
        String[] fields = {"name","description"};
        //分词器
        Analyzer analyzer = new StandardAnalyzer();
        //以下设置的效果:当搜索的关键字在name存在时,会优先将name包含关键字的内容排序在最前面
        Map<String, Float> boosts = new HashMap<String,Float>();
        boosts.put("name", 200f);
        //多域查询对象
        MultiFieldQueryParser parser= new MultiFieldQueryParser(fields, analyzer, boosts);
        //设置查询条件
        Query query = parser.parse("lucene");
        //查询
        query(query);

结果如下,可以发现name包含lucene关键字的数据排在了第一位:

共查询到数据总数为:2

ID:1
name:java lucene
price:11.23
pic:null
description:给你推荐一个写得非常用心的Java基础教程:Java入门基础教程 | 天码营这个教程将Java的入门基础知识贯穿在一个实例中,逐步深入,可以帮助你快速进入Java编程的世界。万事开头难,逐步跟着这个教程走一遍,对Java应该就会有一种入门的感觉了。然后再去学习更高级的主题,或者更深入地学习其中的某些知识点。第1课 Java开发环境安装与配置 第2课 第一个Java程序 第3课 面向对象基础 第4课 基本数据类型 第5课 运算符 第6课 字符串操作 第7课 程序的控制流 第8课 静态变量与静态方法 第9课 Java集合 第10课 封装与继承 第11课 抽象类与接口 第12课 异常处理 第13课 综合实例 第14课 Eclipse的安装与使用

作者:David
链接:https://www.zhihu.com/question/25255189/answer/86898400
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
==================================


ID:2
name:solx 
price:12.55
pic:null
description:Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。[1] 
==================================




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值