Lucene索引库维护、搜索、中文分词器
删除索引(文档)
需求
某些图书不再出版销售了,我们需要从索引库中移除该图书。
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读取内容。
最新文章
- ASP.NET Core 中文文档 第四章 MVC(2.1)模型绑定
- PHP求余函数fmod()
- Android应用:StatusBar状态栏、NavigationBar虚拟按键栏、ActionBar标题栏、Window屏幕内容区域等的宽高
- VSS提示";Could not find the Visual SourceSafe Internet Web Service connection information for the specified database
- db2icrt创建实例,提示主机名无效
- JDBC链接oracle已经mysql的测试
- ASP.NET MVC ViewData/ViewBag 简单小结
- 如何忽略usb host 模式设备连接确认对话框
- Dot Net设计模式—MVC模式
- hdu 5147 Sequence II
- border粗细不一
- [Hapi.js] View engines
- 使用公用表表达式(CTE)
- MTD设备驱动
- AlloyTouch之select选择插件
- socket__服务端、客户端(注释版)
- 显示图像的SIFT flow描述子
- linux根目录下的各文件夹含义说明
- nc/netcat命令
- VisualSVN设置提交时必须输入日志信息
热门文章
- python setup.py install 报错【Project namexxx was given, but was not able to be found.】
- kvm 虚拟机中鼠标不同步的问题解决方法
- Python之运维
- swf反编辑软件带弹窗和跳转swf文件
- 使用服务进程启动asp.net core程序
- 用maven整合SSM中jsp运行报404和500问题解决方案
- 善用Bash history 命令
- pymssql 介绍
- Avtiviti工作流规范 BPM与BPMN
- springcloudalibaba与nacos服务注册流程图