zoukankan      html  css  js  c++  java
  • lucene 初探

    lucene初探, 是为了后面solr做准备的. 如果跳过lucene, 直接去看solr, 估计有点懵. 

    由于时间的关系, lucene查询方法也有多个, 所以单独出来.

     一. 精确查询

         /**
         * 获取 查找对象
         * @return
         * @throws Exception
         */
        private IndexSearcher getSearcher() throws Exception {
            //1. 创建一个directory对象, 也就是索引库存放的位置
            Directory directory = FSDirectory.open(new File(indexDir));
    
            //2. 创建一个indexReader对象, 需要指定directory
            IndexReader indexReader = DirectoryReader.open(directory);
    
            //3. 创建一个indexSearcher对象, 需要指定indexReader对象
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    
            return indexSearcher;
        }
    
         /**
         * 输出信息到控制台
         * @param indexSearcher
         * @param query
         * @throws Exception
         */
        public void sout(IndexSearcher indexSearcher, Query query) throws Exception {
            //5. 执行查询
            TopDocs topDocs = indexSearcher.search(query, 5);
    
            //6. 返回查询结果
            ScoreDoc[] scoreDocs = topDocs.scoreDocs;
            for (ScoreDoc scoreDoc : scoreDocs) {
                //获取文档id
                int doc = scoreDoc.doc;
                //根据文档id获取文档
                Document document = indexSearcher.doc(doc);
                //文件名字
                String fileName = document.get("fileName");
                //文件大小
                String fileSize = document.get("fileSize");
                //文件路径
                String filePath = document.get("filePath");
                //文件内容
                String fileContent = document.get("fileContent");
    
                System.out.println("fileName : " + fileName);
                System.out.println("fileSize : " + fileSize);
                System.out.println("filePath : " + filePath);
                System.out.println("fileContent : " + fileContent);
                System.out.println("-----------------------");
            }
        }
    
         /**
         * 精确查询
         *
         * @throws Exception
         */
        @Test
        public void searchIndex() throws Exception {
    
            //1. 获取查询对象
            IndexSearcher indexSearcher = getSearcher();
    
            //2. 创建一个TermQuery对象, 指定查询的域和查询的关键词
            Query query = new TermQuery(new Term("fileName", "生活"));
    
            sout(indexSearcher, query);
    
            //3. 关闭IndexReader 对象
            indexSearcher.getIndexReader().close();
        }

    在查询的时候, 新建一个Term对象, 进去精确匹配. 前一篇提到过, 经过分词器分下来的每一个词或者一段话, 就是一个Term.

    这里在新建Term的时候, 传入的是 域名 和 要搜索的词.

    这里, 一个Term对象, 只有一个域, 那如果我想查询多个域怎么办呢.

    二. 组合查询

    /**
     * 组合查询
     */
    @Test
    public void queryBoolean() throws Exception {
        IndexSearcher searcher = getSearcher();
    
        BooleanQuery query = new BooleanQuery();
    
        Query query1 = new TermQuery(new Term("fileName", "生活"));
        Query query2 = new TermQuery(new Term("fileContent", "生活"));
    
        query.add(query1, BooleanClause.Occur.MUST);
        query.add(query2, BooleanClause.Occur.SHOULD);
    
        //System.out.println(query);
    
        sout(searcher, query);
    
        searcher.getIndexReader().close();
    }

    这里的Occur枚举值, 有三个, must, should, must_not .

    must : 相当于sql里面的 and 连接

    should : 相当于 or , 可有可没有

    must_not : 相当于 != , 不包含

    这里如果打印query, 会显示:  +fileName:生活  fileContent:生活

    这是lucene的一种语法, lucene可以根据语法来查询数据. 后面会提到. 如果是must_not , 则使用减号. 

    如: 将上面的query2使用 MUST_NOT 连接, 则显示成: +fileName:生活  -fileContent:生活

    三 . 查询所有

    一般查询数据库的时候, 都会提供一个 getAll 方法, 用于查询满足条件的所有数据, 当不传条件时, 就查询所有

    lucene也提供了一个查询所有的方法 : MatchAllDocsQuery 

    /**
     * 查询所有
     *
     * @throws Exception
     */
    @Test
    public void queryAll() throws Exception {
        IndexSearcher searcher = getSearcher();
    
        Query query = new MatchAllDocsQuery();
    
        sout(searcher, query);
    
        searcher.getIndexReader().close();
    }

    四. 数值区间查询

    /**
     * 数值区间查询
     *
     * @throws Exception
     */
    @Test
    public void queryNumericRange() throws Exception {
        IndexSearcher searcher = getSearcher();
    
        Query query = NumericRangeQuery.newLongRange("fileSize", 10L, 647L, true, true);
    
        sout(searcher, query);
    
        searcher.getIndexReader().close();
    }

    这里的语法输出就是 :  fileSize:[40 to 647]

    这是因为我后面两个都设置为true, 表示包含关系. 如果都设置为false, 就是 {40 to 647}

    五. 分词器解析查询

    如前面提到的, 我输入一句话查询, 结果展示的结果却并不是按照我输入的全匹配结果. 

    那是因为在查询之前, 对输入的信息, 进行了分词器解析, 然后根据解析结果, 再去查询数据.

    /**
     * 条件解析对象查询
     *
     * @throws Exception
     */
    @Test
    public void queryParser() throws Exception {
    
        IndexSearcher searcher = getSearcher();
    
        QueryParser queryParser = new QueryParser("fileName", new IKAnalyzer());
    
        //Query query = queryParser.parse("*:*");
        Query query = queryParser.parse("fileName:这花好漂亮");
        //Query query = queryParser.parse("花");
    
        sout(searcher, query);
    
        searcher.getIndexReader().close();
    }

    *:* 表示查询所有. 不管是哪个域.

    fileName:这花好漂亮 : 表示在fileName域中, 将 "这花好漂亮" 分词解析后, 进行查询

    花 : 在fileName域中, 查询花. 因为在QueryParse创建的时候, 指定了域为 fileName

    即使我在QueryParser里面指定了要查询的域, 但是在parse的时候, 我可以重新指定域.

    这里需要注意的是, 在上面数值区间查询的时候, 如果我直接写语法进去查询, 是查不出来的. 因为数值类型变了. 通过语法输进去, 变成字符串类型了. 

    从结果中可以看到, 我输入 这花好漂亮, 查出来的却是 军中绿花. 这就是分词的作用了.

    六. 多域分词查询

    /**
     * 条件解析对象查询
     *
     * @throws Exception
     */
    @Test
    public void queryMultiParser() throws Exception {
    
        IndexSearcher searcher = getSearcher();
    
        String[] fields = {"fileName", "fileContent"};
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
    
        Query query = queryParser.parse("生活大爆炸");
    
        sout(searcher, query);
    
        searcher.getIndexReader().close();
    }

    多域分词查询, 没啥好说的了. 

  • 相关阅读:
    JDBC初体验
    Linux的常用命令--文件的相关操作
    Spring框架之AOP的基本配置
    坦克大战系列7-策略分析之扫描策略和移动策略
    坦克大战系列8-策略分析之瞄准策略
    CF846F Random Query
    CF388C Fox and Card Game
    CF1097F Alex and a TV Show
    CF1276C Beautiful Rectangle
    [SDOI2016]征途
  • 原文地址:https://www.cnblogs.com/elvinle/p/8110258.html
Copyright © 2011-2022 走看看