博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lucene 初探 - 查询
阅读量:4356 次
发布时间:2019-06-07

本文共 5005 字,大约阅读时间需要 16 分钟。

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对象, 只有一个域, 那如果我想查询多个域怎么办呢.

 

二. 组合查询

/** * 组合查询 */@Testpublic 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 */@Testpublic void queryAll() throws Exception {    IndexSearcher searcher = getSearcher();    Query query = new MatchAllDocsQuery();    sout(searcher, query);    searcher.getIndexReader().close();}

 

四. 数值区间查询

/** * 数值区间查询 * * @throws Exception */@Testpublic 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 */@Testpublic 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 */@Testpublic 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();}

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

转载于:https://www.cnblogs.com/dudadi/p/8127685.html

你可能感兴趣的文章
Python3.x:抢票
查看>>
前端三大主流框架的对比React、Vue、Angular 所谓是是三分天下
查看>>
SLAM入门之视觉里程计(6):相机标定 张正友经典标定法详解
查看>>
从开发消费者变成开发生产服务者
查看>>
玩转html5(三)---智能表单(form),使排版更加方便
查看>>
JavaSE-17 泛型
查看>>
net core静态文件 访问除默认目录文件配置
查看>>
mysql—数据库优化——如何选择合适的索引
查看>>
数据库基础
查看>>
百度地图API示例之添加自定义控件
查看>>
计时器
查看>>
Spring学习笔记——Spring MVC表单控制器(SimpleFormController)
查看>>
c++学习笔记之函数重载和模板理解
查看>>
完美世界笔试题-递增子序列B-最长递增子序列打印
查看>>
ImageView实现适屏和裁剪图片功能
查看>>
iOS开发--1.对runtime的理解和整理
查看>>
清除浮动 -- 具有兼容性
查看>>
CF778D Parquet Re-laying 构造
查看>>
SpringMVC如何接收application/json内容编码类型的参数?
查看>>
【推荐系统】neural_collaborative_filtering(源码解析)
查看>>