Lucene的查询及高级内容

Lucene查询

基本查询:

    @Test
    public void baseQuery() throws Exception {
        //1. 创建查询的核心对象
        FSDirectory d = FSDirectory.open(new File("H:\test"));
        IndexReader reader = DirectoryReader.open(d);
        IndexSearcher indexSearcher = new IndexSearcher(reader);

        //2. 执行查询
        QueryParser queryParser = new QueryParser("content", new IKAnalyzer());
        Query query = queryParser.parse("剑来");
        TopDocs topDocs = indexSearcher.search(query, 10);

        //3. 获取文档id
        ScoreDoc[] scoreDocs = topDocs.scoreDocs; //获取得分文档集合
        for (ScoreDoc scoreDoc : scoreDocs) {
            int id = scoreDoc.doc;//获取文档id
            float score = scoreDoc.score;// 返回此文档的匹配度

            Document doc = indexSearcher.doc(id);
            String docId = doc.get("id");
            String content = doc.get("content");
            System.out.println(docId + "   " + content + "  " + "匹配度:" + score);
        }
    }

多样化查询:

    //提取一个查询的方法
    public void query(Query query) throws Exception {

        //1. 创建 查询的核心对象
        IndexReader reader = DirectoryReader.open(FSDirectory.open(new File("H:\test")));
        IndexSearcher indexSearcher = new IndexSearcher(reader);

        //3. 执行查询
        TopDocs topDocs = indexSearcher.search(query, 10);

        ScoreDoc[] scoreDocs = topDocs.scoreDocs;//获取得分文档的集合
        for (ScoreDoc scoreDoc : scoreDocs) {
            //获取文档id
            int docId = scoreDoc.doc;
            //获取文档得分
            float score = scoreDoc.score;
            //根据id获取文档
            Document doc = indexSearcher.doc(docId);
            String content = doc.get("content");
            String title = doc.get("title");
            System.out.println("匹配度:" + score + content + "  " + title);

        }
    }

    // 词条查询
    @Test
    public void termQuery() throws Exception {
        //创建词条对象
        //注意: 词条是不可在分割的, 词条可以是一个字, 也可以是一句话
        //使用场景: 主要是针对的是不可在分割的字段, 例如id
        //由于其不可再分, 可以搜索  全文, 但是不能搜索 全文检索
        TermQuery termQuery = new TermQuery(new Term("content", "全文"));
        query(termQuery);
    }

    // 通配符查询
    @Test
    public void wildcardQuery() throws Exception {

        //通配符:
        //*:  代表多个字符
        //?: 代表一个占位符
        WildcardQuery wildcardQuery = new WildcardQuery(new Term("content", "?uce*"));
        query(wildcardQuery);

    }

    //模糊查询
    @Test
    public void fuzzQuery() throws Exception {
        /**
         * 模糊查询:
         *      指的是通过替换, 补位, 移动 能够在二次切换内查询数据即可返回
         *      参数1: term  指定查询的字段和内容
         *      参数2: int n   表示最大编辑的次数  最大2
         *
         */
        FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("content", "lucene"), 1);
        query(fuzzyQuery);
    }

    // 数值范围查询
    @Test
    public void numericRangeQuery() throws Exception {
        /**
         * 获取NumericRangeQuery的方式:
         *      通过提供的静态方法获取:
         *          NumericRangeQuery.newIntRange()
         *          NumericRangeQuery.newFloatRange()
         *          NumericRangeQuery.newDoubleRange()
         *          NumericRangeQuery.newLongRange()
         *
         *
         * 数值范围查询:
         *      参数1: 指定要查询的字段
         *      参数2: 指定要查询的开始值
         *      参数3: 指定要查询的结束值
         *      参数4: 是否包含开始
         *      参数5: 是否包含结束
         */

        NumericRangeQuery numericRangeQuery = NumericRangeQuery.newIntRange("id", 2, 4, false, false);
        query(numericRangeQuery);
    }

    // 组合查询
    @Test
    public void testBooleanQuery() throws Exception {

        Query query1 = NumericRangeQuery.newLongRange("id", 2l, 4l, true, true);
        Query query2 = NumericRangeQuery.newLongRange("id", 0l, 3l, true, true);

        // boolean查询本身没有查询条件,它可以组合其他查询
        BooleanQuery query = new BooleanQuery();
        // 交集: Occur.MUST + Occur.MUST
        // 并集:Occur.SHOULD + Occur.SHOULD
        // 非:Occur.MUST_NOT
        query.add(query1, BooleanClause.Occur.SHOULD);
        query.add(query2, BooleanClause.Occur.SHOULD);

        query(query);
    }

Lucene高级内容:

高亮:

    // 高亮显示
    @Test
    public void testHighlighter() throws Exception {
        // 目录对象
        Directory directory = FSDirectory.open(new File("H:\test"));
        // 创建读取工具
        IndexReader reader = DirectoryReader.open(directory);
        // 创建搜索工具
        IndexSearcher searcher = new IndexSearcher(reader);

        QueryParser parser = new QueryParser("title", new IKAnalyzer());
        Query query = parser.parse("谷歌地图");
        
        // 格式化器
        Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");
        Scorer scorer = new QueryScorer(query);
        // 准备高亮工具
        Highlighter highlighter = new Highlighter(formatter, scorer);
        // 搜索
        TopDocs topDocs = searcher.search(query, 10);
        System.out.println("本次搜索共" + topDocs.totalHits + "条数据");
        
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            // 获取文档编号
            int docID = scoreDoc.doc;
            Document doc = reader.document(docID);
            System.out.println("id: " + doc.get("id"));
            
            String title = doc.get("title");
            // 用高亮工具处理普通的查询结果,参数:分词器,要高亮的字段的名称,高亮字段的原始值
            String hTitle = highlighter.getBestFragment(new IKAnalyzer(), "title", title);
            
            System.out.println("title: " + hTitle);
            // 获取文档的匹配度
            System.out.println("匹配度:" + scoreDoc.score);
        }
    }

排序:

    // 排序
    @Test
    public void testSortQuery() throws Exception {
        // 目录对象
        Directory directory = FSDirectory.open(new File("H:\test"));
        // 创建读取工具
        IndexReader reader = DirectoryReader.open(directory);
        // 创建搜索工具
        IndexSearcher searcher = new IndexSearcher(reader);
        
        QueryParser parser = new QueryParser("title", new IKAnalyzer());
        Query query = parser.parse("谷歌地图");
        
        // 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
        Sort sort = new Sort(new SortField("id", Type.LONG, true));
        // 搜索
        TopDocs topDocs = searcher.search(query, 10,sort);
        System.out.println("本次搜索共" + topDocs.totalHits + "条数据");
        
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (ScoreDoc scoreDoc : scoreDocs) {
            // 获取文档编号
            int docID = scoreDoc.doc;
            Document doc = reader.document(docID);
            System.out.println("id: " + doc.get("id"));
            System.out.println("title: " + doc.get("title"));
        }
    }

分页:

    @Test
    public void testPageQuery() throws Exception {
        // 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数:
        int pageSize = 2;// 每页条数
        int pageNum = 3;// 当前页码
        int start = (pageNum - 1) * pageSize;// 当前页的起始条数
        int end = start + pageSize;// 当前页的结束条数(不能包含)
        
        // 目录对象
        Directory directory = FSDirectory.open(new File("H:\test"));
        // 创建读取工具
        IndexReader reader = DirectoryReader.open(directory);
        // 创建搜索工具
        IndexSearcher searcher = new IndexSearcher(reader);
        
        QueryParser parser = new QueryParser("title", new IKAnalyzer());
        Query query = parser.parse("谷歌地图");
        
        // 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
        Sort sort = new Sort(new SortField("id", Type.LONG, false));
        // 搜索数据,查询0~end条
        TopDocs topDocs = searcher.search(query, end,sort);
        System.out.println("本次搜索共" + topDocs.totalHits + "条数据");
        
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        for (int i = start; i < end; i++) {
            ScoreDoc scoreDoc = scoreDocs[i];
            // 获取文档编号
            int docID = scoreDoc.doc;
            Document doc = reader.document(docID);
            System.out.println("id: " + doc.get("id"));
            System.out.println("title: " + doc.get("title"));
        }
    }

加权因子:

  • Lucene会对搜索的结果的匹配度进行一个加分, 用来表示数据和词条关联性的强弱, 得分越高, 表示匹配度越高, 排名越靠前

  • Lucene支持对某一个字段设置加权因子, 来提高其打分, 使其排名更加靠前, 这样当用户搜索的时候, 便可以将此词条对应的文档展示在最前面

TextField textField = new TextField("content","lucene加权因子", Store.YES);
textField.setBoost(10);
原文地址:https://www.cnblogs.com/blazeZzz/p/9436129.html