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读取内容。
Lucene索引库维护、搜索、中文分词器的更多相关文章
- Lucene全文检索_分词_复杂搜索_中文分词器
1 Lucene简介 Lucene是apache下的一个开源的全文检索引擎工具包. 1.1 全文检索(Full-text Search) 1.1.1 定义 全文检索就是先分词创建索引,再执行搜索的过 ...
- Lucene全文搜索之分词器:使用IK Analyzer中文分词器(修改IK Analyzer源码使其支持lucene5.5.x)
注意:基于lucene5.5.x版本 一.简单介绍下IK Analyzer IK Analyzer是linliangyi2007的作品,再此表示感谢,他的博客地址:http://linliangyi2 ...
- Elasticsearch的索引模块(正排索引、倒排索引、索引分析模块Analyzer、索引和搜索、停用词、中文分词器)
正向索引的结构如下: “文档1”的ID > 单词1:出现次数,出现位置列表:单词2:出现次数,出现位置列表:…………. “文档2”的ID > 此文档出现的关键词列表. 一般是通过key,去 ...
- 11大Java开源中文分词器的使用方法和分词效果对比,当前几个主要的Lucene中文分词器的比较
本文的目标有两个: 1.学会使用11大Java开源中文分词器 2.对比分析11大Java开源中文分词器的分词效果 本文给出了11大Java开源中文分词的使用方法以及分词结果对比代码,至于效果哪个好,那 ...
- Lucene的中文分词器
1 什么是中文分词器 学过英文的都知道,英文是以单词为单位的,单词与单词之间以空格或者逗号句号隔开. 而中文的语义比较特殊,很难像英文那样,一个汉字一个汉字来划分. 所以需要一个能自动识别中文语义的分 ...
- Lucene 03 - 什么是分词器 + 使用IK中文分词器
目录 1 分词器概述 1.1 分词器简介 1.2 分词器的使用 1.3 中文分词器 1.3.1 中文分词器简介 1.3.2 Lucene提供的中文分词器 1.3.3 第三方中文分词器 2 IK分词器的 ...
- Solr7.1---数据库导入并建立中文分词器
这里只是告诉你如何导入,生产环境不要这样部署你的solr服务. 首先修改solrConfig.xml文件 备份_default文件夹 修改solrconfig.xml 加入如下内容 官方示例:< ...
- (五)Lucene——中文分词器
1. 什么是中文分词器 对于英文,是安装空格.标点符号进行分词 对于中文,应该安装具体的词来分,中文分词就是将词,切分成一个个有意义的词. 比如:“我的中国人”,分词:我.的.中国.中国人.国人. 2 ...
- ElasticSearch7.3学习(十五)----中文分词器(IK Analyzer)及自定义词库
1. 中文分词器 1.1 默认分词器 先来看看ElasticSearch中默认的standard 分词器,对英文比较友好,但是对于中文来说就是按照字符拆分,不是那么友好. GET /_analyze ...
随机推荐
- Mybatis入门(四)------联表查询
Mybatis联表查询 一.1对1查询 1.数据库建表 假设一个老师带一个学生 CREATE TABLE teacher( t_id INT PRIMARY KEY, t_name VARCHAR(3 ...
- python2-dpkt 下载
原文链接:https://centos.pkgs.org/7/forensics-x86_64/python2-dpkt-1.9.2-2.el7.noarch.rpm.html .Download c ...
- selenium定位方法(一)
selenium定位方法-(一) 1.定位页面元素的方式(By类的方法) 1)id定位:通过页面元素的id属性值来定位一个页面元素 注意事项:如果每次刷新网页之后元素的id属性值都不同,说 ...
- Python九九乘法表(正序和逆序)
正序: for i in range(1,10): for j in range(1,i+1): print(str(i)+"*"+str(j)+"="+str ...
- Http请求-okhttp3基本用法
简介 HTTP是现代应用常用的一种交换数据和媒体的网络方式,高效地使用HTTP能让资源加载更快,节省带宽.OkHttp是一个高效的HTTP客户端,它有以下默认特性: 支持HTTP/2,允许所有同一个主 ...
- 区块链入门到实战(35)之Solidity – 变量作用域
局部变量的作用域仅限于定义它们的函数,但是状态变量可以有三种作用域类型. Public – 公共状态变量可以在内部访问,也可以通过消息访问.对于公共状态变量,将生成一个自动getter函数. Inte ...
- 1、Entity Framework Core 3.1入门教程-概述和准备工作
本文章是根据 微软MVP solenovex(杨旭)老师的视频教程编写而来,再加上自己的一些理解. 视频教程地址:https://www.bilibili.com/video/BV1xa4y1v7rR ...
- Windows servers 2008 环境下,域控DC和DNS,分离搭建过程。
近来做有关于window服务器方面运维的实验,正好借此记录下来,便于日后回顾. 通常情况下,域控DC服务器和DNS服务器一般不在一起,所以需要将其分开建立.而这个时候两个服务器的建立有先后顺序,本文会 ...
- ZERO:点击影响的量化 & 分清SEO的不可抗力
http://www.wocaoseo.com/thread-331-1-1.html 这篇文章基于上篇(http://www.wocaoseo.com/thread-332-1-1.html)的理论 ...
- Three.js学习1_快速入门
快速上手, 搭建第一个3D场景 最重要的一步, 先下载three.js, 引入网页中 <script src="./three.js"></script> ...