删除索引(文档)

需求

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

 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读取内容。

最新文章

  1. ASP.NET Core 中文文档 第四章 MVC(2.1)模型绑定
  2. PHP求余函数fmod()
  3. Android应用:StatusBar状态栏、NavigationBar虚拟按键栏、ActionBar标题栏、Window屏幕内容区域等的宽高
  4. VSS提示"Could not find the Visual SourceSafe Internet Web Service connection information for the specified database
  5. db2icrt创建实例,提示主机名无效
  6. JDBC链接oracle已经mysql的测试
  7. ASP.NET MVC ViewData/ViewBag 简单小结
  8. 如何忽略usb host 模式设备连接确认对话框
  9. Dot Net设计模式—MVC模式
  10. hdu 5147 Sequence II
  11. border粗细不一
  12. [Hapi.js] View engines
  13. 使用公用表表达式(CTE)
  14. MTD设备驱动
  15. AlloyTouch之select选择插件
  16. socket__服务端、客户端(注释版)
  17. 显示图像的SIFT flow描述子
  18. linux根目录下的各文件夹含义说明
  19. nc/netcat命令
  20. VisualSVN设置提交时必须输入日志信息

热门文章

  1. python setup.py install 报错【Project namexxx was given, but was not able to be found.】
  2. kvm 虚拟机中鼠标不同步的问题解决方法
  3. Python之运维
  4. swf反编辑软件带弹窗和跳转swf文件
  5. 使用服务进程启动asp.net core程序
  6. 用maven整合SSM中jsp运行报404和500问题解决方案
  7. 善用Bash history 命令
  8. pymssql 介绍
  9. Avtiviti工作流规范 BPM与BPMN
  10. springcloudalibaba与nacos服务注册流程图