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

来源:互联网 发布:手机调音量软件 编辑:程序博客网 时间:2024/06/01 13:00

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关键字的数据排在了第一位:

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