删除索引(文档)

需求

某些图书不再出版销售了,我们需要从索引库中移除该图书。

 1 @Test
2 public void deleteIndex() throws Exception {
3 // 1、指定索引库目录
4 Directory directory = FSDirectory.open(new File("F:\\lucene\\0719"));
5 // 2、创建IndexWriterConfig
6 IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
7 new StandardAnalyzer());
8 // 3、 创建IndexWriter
9 IndexWriter writer = new IndexWriter(directory, cfg);
10 // 4、通过IndexWriter来删除索引
11 // 删除指定索引
12 writer.deleteDocuments(new Term("name", "apache"));
13 // 5、关闭IndexWriter
14 writer.close();
15
16 System.out.println("删除成功");
17
18 }

清空索引库

 1 @Test
2 public void deleteIndex() throws Exception {
3 // 1、指定索引库目录
4 Directory directory = FSDirectory.open(new File("F:\\lucene\\0719"));
5 // 2、创建IndexWriterConfig
6 IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
7 new StandardAnalyzer());
8 // 3、 创建IndexWriter
9 IndexWriter writer = new IndexWriter(directory, cfg);
10 // 4、通过IndexWriter来删除索引
11 // 删除指定索引
12 writer.deleteAll();
13 // 5、关闭IndexWriter
14 writer.close();
15
16 System.out.println("清空索引库成功");
17
18 }

更新索引(文档)

Lucene更新索引比较特殊,是先删除满足条件的索引,再添加新的索引。

 1 @Test
2 public void updateIndex() throws Exception {
3 // 1、指定索引库目录
4 Directory directory = FSDirectory.open(new File("F:\\lucene\\0719"));
5 // 2、创建IndexWriterConfig
6 IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
7 new StandardAnalyzer());
8 // 3、 创建IndexWriter
9 IndexWriter writer = new IndexWriter(directory, cfg);
10 // 4、通过IndexWriter来修改索引
11 // a)、创建修改后的文档对象
12 Document document = new Document();
13
14 // 文件名称
15 Field filenameField = new StringField("name", "updateIndex", Store.YES);
16 document.add(filenameField);
17
18 // 修改指定索引为新的索引
19 writer.updateDocument(new Term("name", "apache"), document);
20
21 // 5、关闭IndexWriter
22 writer.close();
23
24 System.out.println("更新成功");
25 }

已经知道Lucene是通过IndexSearcher对象,来执行搜索的。那我们为什么还要继续学习Lucene呢?

答:因为在实际的开发中,我们的查询的业务是相对复杂的,比如我们在通过关键词查找的时候,往往进行价格、商品类别的过滤。

而Lucene提供了一套查询方案,供我们实现复杂的查询。

-------------------------------------------------------------------------------------------------------------------------------

创建查询的两种方法

执行查询之前,必须创建一个查询Query查询对象。

Query自身是一个抽象类,不能实例化,必须通过其它的方式来实现初始化。

在这里,Lucene提供了两种初始化Query查询对象的方式。

使用Lucene提供Query子类

Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。

使用TermQuery实例化

Query query = new TermQuery(new Term("name", "lucene"));

使用QueryParse解析查询表达式

QueryParser queryParser = new QueryParser("name", new IKAnalyzer());

Query query = queryParser.parse("name:lucene");

常用的Query子类搜索

TermQuery

特点:查询的关键词不会再做分词处理,作为整体来搜索。代码如下:

 1 /**
2 * Query子类查询之 TermQuery
3 *
4 * 特点:不会再对查询的关键词做分词处理。
5 *
6 * 需要:查询书名与java教程相关书。
7 */
8 @Test
9 public void queryByTermQuery(){
10 //1、获取一个查询对象
11 Query query = new TermQuery(new Term("name", "编程思想"));
12 doSearch(query);
13
14 }
15 private void doSearch(Query query) {
16 try {
17
18
19 //2、创建一个查询的执行对象
20 //指定索引库的目录
21 Directory d = FSDirectory.open(new File("F:\\lucene\\0719"));
22 //创建流对象
23 IndexReader reader = DirectoryReader.open(d);
24 //创建搜索执行对象
25 IndexSearcher searcher = new IndexSearcher(reader);
26
27 //3、执行搜索
28 TopDocs result = searcher.search(query, 10);
29
30 //4、提出结果集,获取图书的信息
31 int totalHits = result.totalHits;
32 System.out.println("共查询到"+totalHits+"条满足条件的数据!");
33 System.out.println("-----------------------------------------");
34 //提取图书信息。
35 //score即相关度。即搜索的关键词和 图书名称的相关度,用来做排序处理
36 ScoreDoc[] scoreDocs = result.scoreDocs;
37
38 for (ScoreDoc scoreDoc : scoreDocs) {
39 /**
40 * scoreDoc.doc的返回值,是文档的id, 即 将文档写入索引库的时候,lucene自动给这份文档做的一个编号。
41 *
42 * 获取到这个文档id之后,即可以根据这个id,找到这份文档。
43 */
44 int docId = scoreDoc.doc;
45 System.out.println("文档在索引库中的编号:"+docId);
46
47 //从文档中提取图书的信息
48 Document doc = searcher.doc(docId);
49 System.out.println("图书id:"+doc.get("id"));
50 System.out.println("图书name:"+doc.get("name"));
51 System.out.println("图书price:"+doc.get("price"));
52 System.out.println("图书pic:"+doc.get("pic"));
53 System.out.println("图书description:"+doc.get("description"));
54 System.out.println();
55 System.out.println("------------------------------------");
56
57 }
58
59 //关闭连接,释放资源
60 if(null!=reader){
61 reader.close();
62 }
63 } catch (Exception e) {
64 e.printStackTrace();
65 }
66 }

NumericRangeQuery

指定数字范围查询.(创建field类型时,注意与之对应)

 1 /**
2 * Query子类查询 之 NumricRangeQuery
3 * 需求:查询所有价格在[60,80)之间的书
4 * @param query
5 */
6 @Test
7 public void queryByNumricRangeQuery(){
8 /**
9 * 第一个参数:要搜索的域
10 * 第二个参数:最小值
11 * 第三个参数:最大值
12 * 第四个参数:是否包含最小值
13 * 第五个参数:是否包含最大值
14 */
15 Query query = NumericRangeQuery.newFloatRange("price", 60.0f, 80.0f, true, false);
16
17 doSearch(query);
18 }

BooleanQuery

BooleanQuery,布尔查询,实现组合条件查询。

 1 /**
2 * Query子类查询 之 BooelanQuery查询 组合条件查询
3 *
4 * 需求:查询书名包含java,并且价格区间在[60,80)之间的书。
5 */
6 @Test
7 public void queryBooleanQuery(){
8 //1、要使用BooelanQuery查询,首先要把单个创建出来,然后再通过BooelanQuery组合
9 Query price = NumericRangeQuery.newFloatRange("price", 60.0f, 80.0f, true, false);
10 Query name = new TermQuery(new Term("name", "java"));
11
12 //2、创建BooleanQuery实例对象
13 BooleanQuery query = new BooleanQuery();
14 query.add(name, Occur.MUST_NOT);
15 query.add(price, Occur.MUST);
16 /**
17 * MSUT 表示必须满足 对应的是 +
18 * MSUT_NOT 必须不满足 应对的是 -
19 * SHOULD 可以满足也可以不满足 没有符号
20 *
21 * SHOULD 与MUST、MUST_NOT组合的时候,SHOULD就没有意义了。
22 */
23
24 doSearch(query);
25 }

通过QueryParser搜索

特点

对搜索的关键词,做分词处理。

语法

基础语法

域名:关键字

实例:name:java

组合条件语法

条件1 AND 条件2

条件1 OR 条件2

条件1 NOT 条件2

QueryParser

 1 /**
2 * 查询解析器查询 之 QueryParser查询
3 */
4 @Test
5 public void queryByQueryParser(){
6 try {
7
8 //1、加载分词器
9 Analyzer analyzer = new StandardAnalyzer();
10
11 /**
12 * 2、创建查询解析器实例对象
13 * 第一个参数:默认搜索的域。
14 * 如果在搜索的时候,没有特别指定搜索的域,则按照默认的域进行搜索
15 * 如何在搜索的时候指定搜索域呢?
16 * 答:格式 域名:关键词 即 name:java教程
17 *
18 * 第二个参数:分词器 ,对关键词做分词处理
19 */
20 QueryParser parser = new QueryParser("description", analyzer);
21
22 Query query = parser.parse("name:java教程");
23
24 doSearch(query);
25
26 } catch (Exception e) {
27 e.printStackTrace();
28 }
29 }

MultiFieldQueryParser

通过MulitFieldQueryParse对多个域查询。

 1 /**
2 * 查询解析器查询 之 MultiFieldQueryParser查询
3 *
4 * 特点:同时指定多个搜索域,并且对关键做分词处理
5 */
6 @Test
7 public void queryByMultiFieldQueryParser(){
8 try {
9
10 //1、定义多个搜索的 name、description
11 String[] fields = {"name","description"};
12 //2、加载分词器
13 Analyzer analyzer = new StandardAnalyzer();
14
15 //3、创建 MultiFieldQueryParser实例对象
16 MultiFieldQueryParser mParser = new MultiFieldQueryParser(fields, analyzer);
17
18 Query query = mParser.parse("lucene教程");
19
20 doSearch(query);
21 } catch (Exception e) {
22 e.printStackTrace();
23 }
24 }

中文分词器

什么是中文分词器

学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开

而中文的语义比较特殊,很难像英文那样,一个汉字一个汉字来划分。

所以需要一个能自动识别中文语义的分词器

使用中文分词器IKAnalyzer

添加jar包

修改分词器代码

1 / 创建中文分词器
2 Analyzer analyzer = new IKAnalyzer();

思考?

在一堆文件中,如何快速根据关键词找出对应的文件?

思路:(1)使用全文检索来解决问题

(2)数据源由数据库变成一堆文件。

(3)从一堆文件中,读出里面的内容,转成文档,创建索引库。

(4)创建索引库之后,再根据关键词搜索索引库,找出文件的名称。

问题:如何读文件的内容?

答:txt文本,直接使用IO即可。

doc|docx  使用POI读取内容。

Lucene索引库维护、搜索、中文分词器的更多相关文章

  1. Lucene全文检索_分词_复杂搜索_中文分词器

    1 Lucene简介 Lucene是apache下的一个开源的全文检索引擎工具包. 1.1 全文检索(Full-text Search)  1.1.1 定义 全文检索就是先分词创建索引,再执行搜索的过 ...

  2. Lucene全文搜索之分词器:使用IK Analyzer中文分词器(修改IK Analyzer源码使其支持lucene5.5.x)

    注意:基于lucene5.5.x版本 一.简单介绍下IK Analyzer IK Analyzer是linliangyi2007的作品,再此表示感谢,他的博客地址:http://linliangyi2 ...

  3. Elasticsearch的索引模块(正排索引、倒排索引、索引分析模块Analyzer、索引和搜索、停用词、中文分词器)

    正向索引的结构如下: “文档1”的ID > 单词1:出现次数,出现位置列表:单词2:出现次数,出现位置列表:…………. “文档2”的ID > 此文档出现的关键词列表. 一般是通过key,去 ...

  4. 11大Java开源中文分词器的使用方法和分词效果对比,当前几个主要的Lucene中文分词器的比较

    本文的目标有两个: 1.学会使用11大Java开源中文分词器 2.对比分析11大Java开源中文分词器的分词效果 本文给出了11大Java开源中文分词的使用方法以及分词结果对比代码,至于效果哪个好,那 ...

  5. Lucene的中文分词器

    1 什么是中文分词器 学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开. 而中文的语义比较特殊,很难像英文那样,一个汉字一个汉字来划分. 所以需要一个能自动识别中文语义的分 ...

  6. Lucene 03 - 什么是分词器 + 使用IK中文分词器

    目录 1 分词器概述 1.1 分词器简介 1.2 分词器的使用 1.3 中文分词器 1.3.1 中文分词器简介 1.3.2 Lucene提供的中文分词器 1.3.3 第三方中文分词器 2 IK分词器的 ...

  7. Solr7.1---数据库导入并建立中文分词器

     这里只是告诉你如何导入,生产环境不要这样部署你的solr服务. 首先修改solrConfig.xml文件 备份_default文件夹 修改solrconfig.xml 加入如下内容 官方示例:< ...

  8. (五)Lucene——中文分词器

    1. 什么是中文分词器 对于英文,是安装空格.标点符号进行分词 对于中文,应该安装具体的词来分,中文分词就是将词,切分成一个个有意义的词. 比如:“我的中国人”,分词:我.的.中国.中国人.国人. 2 ...

  9. ElasticSearch7.3学习(十五)----中文分词器(IK Analyzer)及自定义词库

    1. 中文分词器 1.1 默认分词器 先来看看ElasticSearch中默认的standard 分词器,对英文比较友好,但是对于中文来说就是按照字符拆分,不是那么友好. GET /_analyze ...

随机推荐

  1. oracle 分页的两种方式

    实例:查询5-8名学生的姓名与成绩 --oracle的分页1 between 方式(分三次查询,第一次只作排序,第二次给表加上rownum序列,第三次为查询结果) select s.scorenumb ...

  2. double与Double

    1. double是基本数据类型,Double是原始数据类型(Java 类) 2. double创建引用,Double创建对象 3. double不可以为NULL,Double是类所以其对象是可以为N ...

  3. 跟我一起学.NetCore之日志(Log)模型核心

    前言 鲁迅都说:没有日志的系统不能上线(鲁迅说:这句我没说过,但是在理)!日志对于一个系统而言,特别重要,不管是用于事务审计,还是用于系统排错,还是用于安全追踪.....都扮演了很重要的角色:之前有很 ...

  4. Mac包管理神器:Home-brew

    最近看到一个大神修改的Homebrew国内脚本,安装非常方便,以前使用国外的经常下载不下来,这个感觉是非常快的. Homebrew 国内自动安装脚本 ,修改原脚本中的 clone 操作为“浅拷贝”(- ...

  5. google protocol buffer——protobuf的编码原理二

    这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们主要通 ...

  6. gdb我在我本机上p不了,在别人机子上可以

    gdb我在我本机上p不了,在别人机子上可以,不知道什么 (gdb) p EventFlow->devicetypeThere is no member or method named devic ...

  7. laravel Application实例化后两个方法

    laravel容器初始化registerBaseServiceProviders方法 上篇讲解了laravel容器的基本使用和原理,这篇继续Application构造方法中的registerBaseS ...

  8. Android开发之recycleView详解代码,看完包你熟练掌握recycleView的用法。转自网络经典文章

    来源 http://jinyudong.com/2014/11/13/Introduce-RecyclerView-%E4%B8%80/ 编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在 ...

  9. 【原】通过Jenkin传值进Android代码

    1) Jenkin中用-Pxxxx = yyyy来传值进gradle 2) 在AndroidManifest.xml中定义占位符: <meta-data android:name="X ...

  10. Lua的Full UserData、Light UserData和metatable

    http://lua.2524044.n2.nabble.com/LightUserData-and-metatables-td3807698.html https://www.lua.org/man ...