索引库、文档操作

简介: 本文介绍了Elasticsearch(ES)的核心概念及其与MySQL的对比,涵盖索引(Index)、文档(Document)、字段(Field)和映射(Mapping)等基本结构。通过Kibana使用DSL语句演示了索引库与文档的增删改查操作,并讲解了IK分词器、RestClient API 的使用方法,帮助读者掌握ES在数据存储与搜索分析中的实际应用。

在前面读者朋友们可以了解到ES承载着和MySQL一样的“存储-查询”功能,那么就类似的会有建表语句、表结构、表数据,有了这些才可以存储-查询数据。而这些对应的在ES中是:Mapping映射(表结构-建表语句)、索引库(表本身)、文档(表数据)。本节笔者将带领大家完整上述概念的创建、使用。

1.es的一些概念
elasticsearch中有很多独有的概念,与mysql中略有差别,但也有相似之处。
1.1.文档和字段
elasticsearch是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式后存储在elasticsearch中:

"ID": 1,

"TITLE":"小米手机",

"PRICE":3499

ID

TITLE

PRICE

"ID": 2,

"TITLE":"华为手机",

1

3499

小米手机

"PRICE":4999

2

华为手机

4999

"ID":3,

3

华为小米充电器

49

"TITLE":"华为小米充电器",

"PRICE":49

小米手环

299

"ID": 4,

"小米手环"

"TITLE":"

"PRICE": 299


而Json文档中往往包含很多的字段(Field),类似于数据库中的列。
1.2.索引和映射
索引(Index),就是相同类型的文档的集合。例如:
所有用户文档,就可以组织在一起,称为用户的索引;
所有商品的文档,可以组织在一起,称为商品的索引;
所有订单的文档,可以组织在一起,称为订单的索引;
因此,我们可以把索引当做是数据库中的表。
数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此,索引库中就有映射(mapping),是索引中文档的字段约束信息,类似表的结构约束。

订单索引

用户索引

商品索引

"ID": 1,

"ID": 101,

"TITLE":"小米手机",

"NAME":"张三",

"ID":10,

"USERID": 101,

"PRICE":3499

'AGE":   21

"GOODSID": 1,

"TOTALFEE": 294

}

"ID": 2,

"ID":102,

"华为手机",

"TITLE":

"NAME":"李四",

"PRICE":4999

"AGE": 24

"ID": 11,

"USERID":102,

"GOODSID":2,

"ID": 3,

"TOTALFEE":328

"ID":

:103

"三星手机",

"TITLE"

"NAME":"麻子",

3999

"PRICE":

AGE":18


1.3.mysql与elasticsearch
我们统一的把mysql与elasticsearch的概念做一下对比:

MySQL

Elasticsearch

说明

Table

Index

索引(index),就是文档的集合,类似数据库的表(table)

Row

Document

文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式

Column

Field

字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)

Schema

Mapping

Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)

SQL

DSL

DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

是不是说,我们学习了elasticsearch就不再需要mysql了呢?并不是如此,两者各自有自己的擅长支出:
Mysql:擅长事务类型操作,可以确保数据的安全和一致性
Elasticsearch:擅长海量数据的搜索、分析、计算
因此在企业中,往往是两者结合使用:
对安全性要求较高的写操作,使用mysql实现
对查询性能要求较高的搜索需求,使用elasticsearch实现
两者再基于某种方式,实现数据的同步,保证一致性

搜索

数据同步

CRUD

写操作

MYSQL


1.4.安装es、kibana
1.4.1.安装
参考:链接
1.4.2.分词器
参考:链接
1.4.3.总结
分词器的作用是什么?
创建倒排索引时对文档分词
用户搜索时,对输入的内容分词
IK分词器有几种模式?
ik_smart:智能切分,粗粒度
ik_max_word:最细切分,细粒度
IK分词器如何拓展词条?如何停用词条?
利用config目录的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典
在词典中添加拓展词条或者停用词条
2.索引库操作
索引库就类似数据库表,mapping映射就类似表的结构。我们要向es中存储数据,必须先创建“库”和“表”。
2.1.mapping映射属性
mapping是对索引库中文档的约束,常见的mapping属性包括:
type:字段数据类型,常见的简单类型有:
字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
数值:long、integer、short、byte、double、float、
布尔:boolean
日期:date
对象:object
index:是否创建索引,默认为true
analyzer:使用哪种分词器
properties:该字段的子字段
例如下面的json文档:
对应的每个字段映射(mapping):
age:类型为 integer;参与搜索,因此需要index为true;无需分词器
weight:类型为float;参与搜索,因此需要index为true;无需分词器
isMarried:类型为boolean;参与搜索,因此需要index为true;无需分词器
info:类型为字符串,需要分词,因此是text;参与搜索,因此需要index为true;分词器可以用ik_smart
email:类型为字符串,但是不需要分词,因此是keyword;不参与搜索,因此需要index为false;无需分词器
score:虽然是数组,但是我们只看元素的类型,类型为float;参与搜索,因此需要index为true;无需分词器
name:类型为object,需要定义多个子属性
name.firstName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器
name.lastName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器
2.2.索引库的CRUD
这里我们统一使用Kibana编写DSL的方式来演示。
2.2.1.创建索引库和映射
基本语法:
请求方式:PUT
请求路径:/索引库名,可以自定义
请求参数:mapping映射
格式:
示例:
2.2.2.查询索引库
基本语法:
请求方式:GET
请求路径:/索引库名
请求参数:无
格式:
示例:

"HEIMA"

234567894

"LASTNAME":{

{子,

'ALIASES"

"TYPE":"KEYWORD"

"MAPPINGS

"PROPERTIES":{

"EMAIL":{

"TYPE":"KEYWORD",

"INDEX":FALSE

INFO":{

10

"TEXT",

"TYPE":

11

#查询

:"IK_SMART"

12

"ANALYZER"

GET/HEIMA

13

14

"NAME

15

"PROPERTIES"

"FIRSTNAME"

16

"KEYWORD"

"TYPE"

17

18

19

LASTNAME'

"KEYWORD"

20

"TYPE":

21

22`

23~

24

25


2.2.3.修改索引库
倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引,这简直是灾难。因此索引库一旦创建,无法修改mapping。虽然无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。
语法说明:
示例:

#修改索引库,添加新字段

"ACKNOWLEDGED": TRUE

2

PUT/HEIMA/_MAPPING

D

3

4

"PROPERTIES":

"AGE":{

"INTEGER"

"TYPE"


2.2.4.删除索引库
语法:
请求方式:DELETE
请求路径:/索引库名
请求参数:无
格式:
在kibana中测试:

2

"ACKNOWLEDGED"

TRUE

34

CLICK TO SEND REQUEST

#删除

DELETE/HEIMA


2.2.5.总结
索引库操作有哪些?
创建索引库:PUT /索引库名
查询索引库:GET /索引库名
删除索引库:DELETE /索引库名
添加字段:PUT /索引库名/_mapping
3.文档操作
3.1.新增文档
语法:
示例:
响应:

#插入文档

INDEX":"HEIMA"

POST /HEIMA/_DOC/1

E":" DOC",

TYPE"

"1",

ID"

"INFO":"黑马程序员JAVA讲师",

5

VERSION

"EMAIL": "ZY@ITCAST.CN",

6

'CREATED".

RESULT"

"NAME":

7

SHARDS"

I}

"FIRSTNAME":"云",

"TOTAL": 2,

8

"LASTNAME":"赵"

6

"SUCCESSFUL"

"FAILED":0

10

11

12

_SEQ_NO":0.

13

_PRIMARY_TERM":1

14`}

15


针对同一个index,其中version在每次写操作后都会+1(新增、修改、删除)

HELP

SETTINGS

ORY

1234567

#新增文档

_INDEX" : "HEIMAL8384",

POST /HEIMA18384/_DOC/1

_TYPE" : "_DOC",

ID""

"INFO":"18384明天干啥去呀",

当用户新增文档数据时,如果某个字段为空

:1.

VERSION

"EMAIL":"183@QQ.COM",

SEQ_NO":O,

ES的策略是直接不返回,减少网络开销

"NAME

7

PRIMARY_TERM

1,

"FIRSTNAME":"李",

8

PUNO:

TRUE,

"LASTNAME": "致"

9-

SOURCE

:"18384明天干啥去呀",

'INFO"

10

L

: "183@QQ.COM",

EMAIL

11

67

12

NAME

/HEIMA18384/_DOC/1

GET

:"李",

"FIRSTNAME"

13

"致"

"LASTNAME"

99123

14

15

16

17

18


HELP

SETTINGS

NAME`:

"FIRSTNAME":"李",

INDEX"

"HEIMA18384",

234

"LASTNAME":"致"

DOC"

TYPE

ID""

一旦用户存储进去,就会全量返回

5

VERSION" : 1,

6

SEG_NO":1,

POST /HEIMA18384/_DOC/2

_PRIMARY_TERM" : 1,

7

'FOUND": TRUE,

8

"INFO":"18384明天干啥去呀",

SOURCE'

"EMAIL"."183@QQ.COM",

"INFO":"18384明天干啥去呀",

10

"AGE":200,

11

"EMAIL":"183@QQ.COM",

"NAME":{

12

"AGE":200,

"FIRSTNAME":"李",

13

NAME

"LASTNAME":"致"

"FIRSTNAME" :"李",

14

"LASTNAME" :"致"

15

16-

17

#查询文档

18

GET /HEIMA18384/_DOC/2

19


3.2.查询文档
根据rest风格,新增是post,查询应该是get,不过查询一般都需要条件,这里我们把文档id带上。
语法:
通过kibana查看数据:
查看结果:

123

#查询文档

INDEX":"HEIMA",

GET/HEIMA/_DOC/1

_DOC",

TYPE":

3456

ID":"1",

VERSION":1,

SEQ_NO":0,

7

_PRIMARY_TERM":1

8

'FOUND"

TRUE,

6

SOURCE

":"黑马程序员JAVA讲师",

"INFO"

10

: "ZY@ITCAST.CN",

"EMAIL"

11

"NAME":

12

"FIRSTNAME":"云",

13

"LASTNAME":"赵"

14

15

16

17

18


3.3.删除文档
删除使用DELETE请求,同样,需要根据id进行删除:
语法:
示例:
结果:

#删除文档

INDEX'"

"HEIMA",

DELETE /HEIMA/_DOC/1

3456789

'DOC"

TYPE

"1"

ID"

VERSION"

"DELETED",

'RESULT"

SHARDS

"TOTAL'

60

"SUCCESSFUL":1,

"FAILED":O

10

11

了,

SEQ_NO":1

12

"

13

PRIMARY TERM":1

14`}


3.4.修改文档
修改有两种方式:
全量修改:直接覆盖原来的文档
增量修改:修改文档中的部分字段
3.4.1.全量修改
全量修改是覆盖原来的文档,其本质是:
根据指定的id删除文档
新增一个相同id的文档
注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。
语法:
示例:
3.4.2.增量修改
增量修改是只修改指定id匹配的文档中的部分字段。
语法:
示例:
3.5.总结
文档操作有哪些?
创建文档:POST /{索引库名}/_doc/文档id   { json文档 }
查询文档:GET /{索引库名}/_doc/文档id
删除文档:DELETE /{索引库名}/_doc/文档id
修改文档:
全量修改:PUT /{索引库名}/_doc/文档id { json文档 }
增量修改:POST /{索引库名}/_update/文档id { "doc": {字段}}
4.RestAPI
ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html
其中的Java Rest Client又包括两种:
Java Low Level Rest Client
Java High Level Rest Client
我们学习的是Java HighLevel Rest Client客户端API
4.0.导入Demo工程
4.0.1.导入数据
首先导入提供的数据库数据:

tb_hotel.sql(62 KB)
数据结构如下:
4.0.2.导入项目
然后导入提供的项目:

hotel-demo.zip(132 KB)
项目结构如图:

HOTEL-DEMOD://CODE\HOTEL-DEMO

SERVER:

.IDEA

8089

PORT:

SRC

SPRING:

MAIN

DATASOURCE:

JAVA

5678

URL:JDBC:MYSQL://MYSQL:3306/HEIMA?USESSL-FALSE

CN.ITCAST.HOTEL

USERNAME:ROOT

MAPPER

PASSWORD:123

POJO

DRIVER-CLASS-NAME: COM.MYSQL.JDBC.DRIVER

SERVICE

LOGGING:

HOTELDEMOAPPLICATION

9

LEVEL:

RESOURCES

10

STATIC

CN.ITCAST: DEBUG

11

TEMPLATES

12

PATTERN:

APPLICATIONYAML

DATEFORMAT: MM-DD HH:MM:SS:SSS

13

TEST

14

MYBATISPLUS:

POM.XML

15

CONFIGURATION:

EXTERNAL LIBRARIES

MAP-UNDERSCORE-TO-CAMEL-CASE: TRUE

16

SCRATCHES AND CONSOLES

TYPE-ALIASES-PACKAGE: CN.ITCAST.HOTEL.POJO

17


4.0.3.mapping映射分析
创建索引库,最关键的是mapping映射,而mapping映射要考虑的信息包括:
字段名
字段数据类型
是否参与搜索
是否需要分词
如果分词,分词器是什么?
其中:
字段名、字段数据类型,可以参考数据表结构的名称和类型
是否参与搜索要分析业务来判断,例如图片地址,就无需参与搜索
是否分词呢要看内容,内容如果是一个整体就无需分词,反之则要分词
分词器,我们可以统一使用ik_max_word
来看下酒店数据的索引库结构:
几个特殊字段说明:
location:地理坐标,里面包含精度、纬度
all:一个组合字段,其目的是将多字段的值 利用copy_to合并,提供给用户搜索
地理坐标说明:

小提示

ES中支持两种地理坐标数据类型:

GEO_POINT:由结度(LATITUDE)和经度(LONGITUDE)确定的一个点.例如:"32.8752345,120.2981576"

GEO.SHAPE;有多个GEO.POINT组成的复杂几何图形.例如一条直线,"UNESTRING(77.036533333333339)"


copy_to说明:

小提示

字段拷贝可以使用COPY_TO属性将当前字段拷贝到指定字段.示例:

"ALL": {

"TYPE": "TEXT",

"ANALYZER": "IK_MAX_WORD"

子.

"BRAND":{

"TYPE":"KEYWORD".

"COPY_TO": "ALL"


4.0.4.初始化RestClient
方式一
在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。
分为三步:
1)引入es的RestHighLevelClient依赖:
2)因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:
3)启动类初始化RestHighLevelClient,初始化的代码如下:

(MAPPERSCAN("CN.ITCAST.HOTEL.MAPPER")

@SPRINGBOOTAPPLICATION

PUBLIC CLASS HOTELDEMOAPPLICATION I

PUBLIC STATIC VOID MAIN(STRING[] ARGS) ( SPRINGAPPLICATION.RUN(HOTELDEMOAPPLICATION.CLASS, ANGS);]]

ABEAN

PUBLIC RESTHIGHLEVELCLIENT INITCLIENT() {

RESTHIGHLEVELCLIENT(RESTCLIENT.BUILDER(

RETURN NEW R

HTTPHOST.CREATE("HTTP://192.168.150.101:9200")

));


4)引入
方式二
可以直接在单测类完整创建、初始化
4.1.创建索引库
4.1.1.代码解读
创建索引库的API如下:

请求路径,索引库名称

PUT /HOTEL

"MAPPINGS":

创建索引库代码如下:

"PROPERTIES":

]D": :

"TYPE": "KEYWORD"

'NAME":

@TEST

"TYPE": "TEXT",

VOID TESTCREATEHOTELINDEX() THROWS IOEXCEPTION {

"ANALYZER": "IK MAX WORD"

//1.创建REQUEST对象

WBDRESS":

CREATEINDEXREQUEST REQUEST - NEW CREATEINDEXREQUEST("HOTEL');

PRICE"

2.请求参数,MAPPING_TEMPLATE是静态常量字符串,内容是创建索引库的DSI语句

DSL

"BRAND":

"CITY":

REQUEST.SOURCE(MAPPING_TEMPLATE,XCONTENTTYPE.JSON);

"STARNAME"

1/3.发起请求

"BUSINESS"

"LOCATION":

.CREATE(REQUEST,REQUESTOPTIONS.DEFAULT);

INDICES()

CLIENT

"TYPE":

GEO_POINT"

"PIC":

"TYPE": "KEYWORD",

返回的对象中包含

"INDEX":FALSE

索引库操作的所有方法


代码分为三步:
1)创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。
2)添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。
3)发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。
4.1.2.完整示例
在hotel-demo的cn.itcast.hotel.constants包下,创建一个类,定义mapping映射的JSON字符串常量:
在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现创建索引:
4.2.删除索引库
删除索引库的DSL语句非常简单:
与创建索引库相比:
请求方式从PUT变为DELTE
请求路径不变
无请求参数
所以代码的差异,注意体现在Request对象上。依然是三步走:
1)创建Request对象。这次是DeleteIndexRequest对象
2)准备参数。这里是无参
3)发送请求。改用delete方法
在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现删除索引:
4.3.判断索引库是否存在
判断索引库是否存在,本质就是查询,对应的DSL是:
因此与删除的Java代码流程是类似的。依然是三步走:
1)创建Request对象。这次是GetIndexRequest对象
2)准备参数。这里是无参
3)发送请求。改用exists方法
4.4.总结
JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。
索引库操作的基本步骤:
初始化RestHighLevelClient
创建XxxIndexRequest。XXX是Create、Get、Delete
准备DSL( Create时需要,其它是无参)
发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete
5.RestClient操作文档
为了与索引库操作分离,我们再次参加一个测试类,做两件事情:
初始化RestHighLevelClient
我们的酒店数据在数据库,需要利用IHotelService去查询,所以注入这个接口
5.1.新增文档
我们要将数据库的酒店数据查询出来,写入elasticsearch中。
5.1.1.索引库实体类
数据库查询后的结果是一个Hotel类型的对象。结构如下:
与我们的索引库结构存在差异:
longitude和latitude需要合并为location
因此,我们需要定义一个新的类型,与索引库结构吻合:
5.1.2.语法说明
新增文档的DSL语句如下:
对应的java代码如图

ATEST

VOID TESTINDEXDOCUMENT() THROWS IOEXCEPTION {

索引库名,文档ID

//1.创建REQUEST对象

POST /INDEXNAME/_DOC/1

INDEXREQUEST REQUEST - NEW INDEXREQUEST("INDEXNAME').ID("1');

//2.准备JSON文档

"NAME": "JACK",

: 21J", XCONTENTTYPE.JSON);

REQUEST.SOURCE("\\"NAME\": \"JACK\",

'AGE": 21

JSON文档

"AGE

1/3.发送请求

CLIENT.INDEX(REQUEST, REQUESTOPTIONS.DEFAULT);


可以看到与创建索引库类似,同样是三步走:
1)创建Request对象
2)准备请求参数,也就是DSL中的JSON文档
3)发送请求
变化的地方在于,这里直接使用client.xxx()的API,不再需要client.indices()了。
5.1.3.完整代码
我们导入酒店数据,基本流程一致,但是需要考虑几点变化:
酒店数据来自于数据库,我们需要先查询出来,得到hotel对象
hotel对象需要转为HotelDoc对象
HotelDoc需要序列化为json格式
因此,代码整体步骤如下:
1)根据id查询酒店数据Hotel
2)将Hotel封装为HotelDoc
3)将HotelDoc序列化为JSON
4)创建IndexRequest,指定索引库名和id
5)准备请求参数,也就是JSON文档
6)发送请求
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
5.2.查询文档
5.2.1.语法说明
查询的DSL语句如下:
非常简单,因此代码大概分两步:
准备Request对象
发送请求
不过查询的目的是得到结果,解析为HotelDoc,因此难点是结果的解析。完整代码如下:

@TEST

/INDEXNAME/ DOC/1

GET

VOID TESTGETDOCUMENTBYID() THROWS IOEXCEPTION {

1/1.创建REQUEST对象

: NEW GETREQUEST("INDEXNAME", "1");

GETREQUEST REQUEST

1/2.发送请求,得到结果

_INDEX" : "USERS",

_DOC",

GETRESPONSE RESPONSE - CLIENT.GET(REQUEST, REQUESTOPTIONS.DEFAULT);

TYPE

ID''

1/3.解析结果

_VERSION":1

STRING JSON - RESPONSE.GETSOURCEASSTRING();

LSEQ_NO,.:0,

_PRIMARY_TERM": 1,

SYSTEM.OUT.PRINTLN(JSON);

TRUE

FOUND

SOURCE

"JACK",

NAME

":21

AGE"

可以看到,结果是一个JSON,其中文档放在一个_source属性中,因此解析就是拿到_source,反序列化为Java对象即可。
与之前类似,也是三步走:
1)准备Request对象。这次是查询,所以是GetRequest
2)发送请求,得到结果。因为是查询,这里调用client.get()方法
3)解析结果,就是对JSON做反序列化
5.2.2.完整代码
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
5.3.删除文档
删除的DSL为是这样的:
与查询相比,仅仅是请求方式从DELETE变成GET,可以想象Java代码应该依然是三步走:
1)准备Request对象,因为是删除,这次是DeleteRequest对象。要指定索引库名和id
2)准备参数,无参
3)发送请求。因为是删除,所以是client.delete()方法
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
5.4.修改文档
5.4.1.语法说明
修改我们讲过两种方式:
全量修改:本质是先根据id删除,再新增
增量修改:修改文档中的指定字段值
在RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:
如果新增时,ID已经存在,则修改
如果新增时,ID不存在,则新增
这里不再赘述,我们主要关注增量修改。
代码示例如图:

ATEST

VOID TESTUPDATEDOCUMENTBYID() THROWS IOEXCEPTION ;

//1.创建REQUEST对象

EW UPDATEREQUEST("INDEXNAME", "1");

UPDATEREQUEST REQUEST - NEW U

/USERS/_UPDATE/1

1/2.准备参数,每2个参数为一对

KEY

VALUE

索引库名,

文档ID

"DOC":

REQUEST.DOC(

"NAME": "ROSE",

"AGE",18,

"AGE":18

"NAME", "ROSE"

要修改的字段

);

1/3.更新文档

CLIENT.UPDATE(REQUEST, REQUESTOPTIONS.DEFAULT);


与之前类似,也是三步走:
1)准备Request对象。这次是修改,所以是UpdateRequest
2)准备参数。也就是JSON文档,里面包含要修改的字段
3)更新文档。这里调用client.update()方法
5.4.2.完整代码
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
5.5.批量导入文档
案例需求:利用BulkRequest批量将数据库数据导入到索引库中。
步骤如下:
利用mybatis-plus查询酒店数据
将查询到的酒店数据(Hotel)转换为文档类型数据(HotelDoc)
利用JavaRestClient中的BulkRequest批处理,实现批量新增文档
5.5.1.语法说明
批量处理BulkRequest,其本质就是将多个普通的CRUD请求组合在一起发送。其中提供了一个add方法,用来添加其他请求:

BULKREQUEST.JAVA

ANONYMOUS CLASSES(CTRL++1)

LAMBDAS(CTRL+L)

INHERITED MEMBERS(CTRL+F12)

ADD(DELETEREQUEST):BULKREQUEST

ADD(DOCWRITEREQUEST<?>):BULKREQUEST

ADD(DOCWRITEREQUEST<?>....):BULKREQUEST

ADD(INDEXREQUEST):BULKREQUEST

ADD(ITERABLE<DOCWRITEREQUEST<?>>):BULKREQUEST

ADD(UPDATEREQUEST):BULKREQUEST

APPLYGLOBALMANDATORYPARAMETERS(DOCWRITEREQUEST<?>):VOID


可以看到,能添加的请求包括:
IndexRequest,也就是新增
UpdateRequest,也就是修改
DeleteRequest,也就是删除
因此Bulk中添加了多个IndexRequest,就是批量新增功能了。示例:

@TEST

IOEXCEPTION {

VOID

THROWS

TESTBULK()

1.创建BULK请求

BULKREQUEST REQUEST ; NEW BULKREQUEST();

2.添加要批量提交的请求:这里添加了两个新增文档的请求

REQUEST.ADD(NEW INDEXREQUEST("HOTEL")

.ID("101").SOURCE("JSON SOURCE", XCONTENTTYPE.JSON);

REQUEST.ADD(NEW INDEXREQUEST("HOTEL")

.ID("102").SOURCE("JSON SOURCE2",

XCONTENTTYPE.JSON));

1/3.发起BULK请求

CLIENT.BULK(REQUEST, REQUESTOPTIONS.DEFAULT);


其实还是三步走:
1)创建Request对象。这里是BulkRequest
2)准备参数。批处理的参数,就是其它Request对象,这里就是多个IndexRequest
3)发起请求。这里是批处理,调用的方法为client.bulk()方法
我们在导入酒店数据时,将上述代码改造成for循环处理即可。
5.5.2.完整代码
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:

Java

运行代码复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Test

void testBulkRequest() throws IOException {

// 批量查询酒店数据

List<Hotel> hotels = hotelService.list();


// 1.创建Request

BulkRequest request = new BulkRequest();

// 2.准备参数,添加多个新增的Request

for (Hotel hotel : hotels) {

// 2.1.转换为文档类型HotelDoc

HotelDoc hotelDoc = new HotelDoc(hotel);

// 2.2.创建新增文档的Request对象

request.add(new IndexRequest("hotel")

.id(hotelDoc.getId().toString())

.source(JSON.toJSONString(hotelDoc), XContentType.JSON));

}

// 3.发送请求

client.bulk(request, RequestOptions.DEFAULT);

}

通过指令查询:GET /hotel/_search

SETTINGS HELP

"PIC":

"TOOK" : 1023,

"TYPE": "KEYWORD",

"TIMED_OUT" : FALSE,

"INDEX":FALSE

SHARDS"

"TOTAL" : 1,

'ALL": {

"SUCCESSFUL" : 1,

"TYPE":"TEXT",

"SKIPPED":0,

"ANALYZER": "IK MAX WORD"

8

"FAILED":O

9

总数据量应该跟数据库保持一致

ITE

10

"TOTAL":{

11

'VALUE"

12

200

13

"RELATION

"EG

#查询索引库

24

GET /HOTEL18483

1.0.

"MAX_SCORE

"HITS" : [

16

#查询指定ID文档的数据

17

GET /HOTEL18483/_DOC/36934

: "HOTEL18483",

18

INDEX":

_TYPE": "_DOC",

19

GET /HOTEL18483/_SEARCH

ID":"36934",

20

21

SCORE":1.0.

22

SOURCE

"静安交通路40号",

3元

LADDRESS

"7天酒店"

"BRAND""


5.6.小结
文档操作的基本步骤:
初始化RestHighLevelClient
创建XxxRequest。XXX是Index、Get、Update、Delete、Bulk
准备参数(Index、Update、Bulk时需要)
发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete、bulk
解析结果(Get时需要)

若有收获,就点个赞吧


相关文章
|
1天前
|
数据采集 人工智能 安全
|
11天前
|
云安全 监控 安全
|
2天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
983 151
|
2天前
|
编解码 人工智能 机器人
通义万相2.6,模型使用指南
智能分镜 | 多镜头叙事 | 支持15秒视频生成 | 高品质声音生成 | 多人稳定对话
|
16天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1685 8
|
8天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
630 152
|
10天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
601 15
|
9天前
|
人工智能 自然语言处理 API
Next AI Draw.io:当AI遇见Draw.io图表绘制
Next AI Draw.io 是一款融合AI与图表绘制的开源工具,基于Next.js实现,支持自然语言生成架构图、流程图等专业图表。集成多款主流大模型,提供智能绘图、图像识别优化、版本管理等功能,部署简单,安全可控,助力技术文档与系统设计高效创作。
679 151