微服务:索引库、文档操作
分词器
处理中文分词,一般会使用IK分词器。https://github.com/medcl/elasticsearch-analysis-ik
ik_smart
:最少切分ik_max_word
:最细切分
POST /_analyze
#post请求,解析
{
"text": "兽兽真香,燕燕也香。",
"analyzer": "ik_smart"
}
#ik_smart输出结果为
{
"tokens" : [
{
"token" : "兽",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "兽",
"start_offset" : 1,
"end_offset" : 2,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "真香",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "燕燕",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "也",
"start_offset" : 7,
"end_offset" : 8,
"type" : "CN_CHAR",
"position" : 4
},
{
"token" : "香",
"start_offset" : 8,
"end_offset" : 9,
"type" : "CN_CHAR",
"position" : 5
}
]
}
#ik_max_word输出结果为
扩展词词典
随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“传智播客” 等。
所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。
打开IK分词器config目录:
2)在IKAnalyzer.cfg.xml配置文件内容添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-->
<entry key="ext_dict">ext.dic</entry>
</properties>
3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改
奥力给
4)重启elasticsearch
docker restart es
# 查看 日志
docker logs -f elasticsearch
日志中已经成功加载ext.dic配置文件
5)测试效果:
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "就业超过90%,奥力给!"
}
注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑
停用词词典
在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。
IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。
1)IKAnalyzer.cfg.xml配置文件内容添加:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典-->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典 *** 添加停用词词典-->
<entry key="ext_stopwords">stopword.dic</entry>
</properties>
3)在 stopword.dic 添加停用词
草
分词器的作用是什么?
-
创建倒排索引时对文档分词
-
用户搜索时,对输入的内容分词
IK分词器有几种模式?
-
ik_smart:智能切分,粗粒度
-
ik_max_word:最细切分,细粒度
IK分词器如何拓展词条?如何停用词条?
-
利用config目录的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典
-
在词典中添加拓展词条或者停用词条
索引库
Mapping——映射
mapping是对索引库中文档的约束,常见的mapping属性包括:
-
type:字段数据类型,常见的简单类型有:
-
字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
-
数值:long、integer、short、byte、double、float、
-
布尔:boolean
-
日期:date
-
对象:object
-
-
index:是否创建索引,默认为true
-
analyzer:使用哪种分词器
-
properties:该字段的子字段
创建索引库
#如:
PUT /heima
{
"mappings": {
"properties": {
"info":{
"type": "text",
"analyzer": "ik_smart"
},
"email":{
"type": "keyword",
"index": "false"
},
"name":{
"properties": {
"firstName": {
"type": "keyword"
}
}
},
// ... 略
}
}
}
查看索引库
GET /索引库名
#举例:
GET /heima
删除索引库
DELETE /索引库名
#举例:
DELETE /heima
修改索引库
ES中禁止修改索引库。
但是可以新增字段名
PUT /索引库名/_mapping
{
"properties": {
"新字段名":{
"type": "integer"
}
}
}
#举例
PUT /heima/_mapping
{
"properties": {
"age":{
"type": "integer"
}
}
}
文档操作
新增文档
POST /索引库名/_doc/文档id
#如:
POST /heima/_doc/1
{
"info": "黑马程序员Java讲师",
"email": "zy@itcast.cn",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
查询文档
GET /索引库名/_doc/文档id
#如:
GET /heima/_doc/1
删除文档
DELETE /索引库名/_doc/文档id
#如:
DELETE /heima/_doc/1
修改文档
- 方式一:全量修改,会删除旧文档,添加新文档
PUT /索引库名/_doc/文档id
#如:
PUT /heima/_doc/1
{
"info": "黑马程序员高级Java讲师",
"email": "zy@itcast.cn",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
如果文档id不存在,则不会删除,但是会创建新的文档
- 增量修改
POST /索引库名/_update/文档id
#如:
POST /heima/_update/1
{
"doc": {
"email": "ZhaoYun@itcast.cn"
}
}
使用java操作索引库和文档
利用JavaRestClient实现创建、删除索引库,判断索引库是否存在
基本步骤如下:
- 分析数据结构,定义mapping属性
PUT /hotel
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name":{
"type": "text",
"analyzer": "ik_max_word",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false
},
"price":{
"type": "integer"
},
"score":{
"type": "integer"
},
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword",
"copy_to": "all"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
copy_to说明:
-
初始化JavaRestClient
- 引入依赖
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>
- 因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:
<properties> <java.version>1.8</java.version> <elasticsearch.version>7.12.1</elasticsearch.version> </properties>
- 初始化RestHighLevelClient:
public class HotelIndexTest { private RestHighLevelClient client; /** * 这个方法用来初始化client */ @BeforeEach void setUp() { this.client=new RestHighLevelClient(RestClient.builder( HttpHost.create("192.168.1.2:9200") )); } /** * 这个方法用来销毁client * @throws IOException */ @AfterEach void tearDown() throws IOException { this.client.close(); } @Test void test1(){ //测试逻辑 } }
-
利用JavaRestClient创建索引库
/** * 这个方法用来创建索引库 * @throws IOException */ @Test void create() throws IOException { //1.创建Request对象 CreateIndexRequest request = new CreateIndexRequest("hotel"); //2.准备请求参数:DSL语句 request.source(MAPPING_TEMPLATE, XContentType.JSON); //3.发送请求 client.indices().create(request, RequestOptions.DEFAULT); }
-
利用JavaRestClient删除索引库
/** * 这个方法用来删除索引库 * @throws IOException */ @Test void delete() throws IOException { //1.创建Request对象 DeleteIndexRequest request = new DeleteIndexRequest("hotel"); //2.发送请求 client.indices().delete(request, RequestOptions.DEFAULT); }
-
利用JavaRestClient判断索引库是否存在
/** * 这个方法用来判断索引库是否存在 * @throws IOException */ @Test void isExist() throws IOException { //1.创建Request对象 GetIndexRequest request = new GetIndexRequest("hotel"); //2.发送请求 boolean exists = client.indices().exists(request, RequestOptions.DEFAULT); //3.输出 System.out.println(exists?"索引库已经存在":"索引库不存在"); }