为什么建设网站要年年交钱,网页设计与网站开发pdf,天津通用网站建设收费,wordpress 注册 模版目录
es索引库操作
mapping映射操作
索引库的CURD操作
1.创建索引库和映射
编辑 2.查询索引库
3.删除索引库
4.修改索引库
5.总结 文档的CURD操作
1.新增文档
2.查询文档 3.删除文档
4.修改文档
全量修改
增量修改
5.总结
RestAPI
使用API例子
需要的数…目录
es索引库操作
mapping映射操作
索引库的CURD操作
1.创建索引库和映射
编辑 2.查询索引库
3.删除索引库
4.修改索引库
5.总结 文档的CURD操作
1.新增文档
2.查询文档 3.删除文档
4.修改文档
全量修改
增量修改
5.总结
RestAPI
使用API例子
需要的数据库表结构 分析这个数据表的结构然后构建索引库和mapping 索引库结构说明 初始化RestClient
1.导入es的RestHighLevelClient依赖
2.因为SpringBoot默认的ES版本是7.6.2所以我们需要覆盖默认的ES版本换成自己的es版本 3.初始化RestHighLevelClient即维护一个bean到IoC容器
使用RestHighLevelClient构建索引库及其mapping
1.构建json数据常量 2.创建索引库 3.测试是否构建成功 使用RestHighLevelClient查询索引库和删除索引库
总结 RestClient操作文档
新增文档
构建索引库实体类
因此我们需要定义一个新的类型与索引库结构吻合 新增文档的DSL语句如下 代码实现
测试 查询文档
修改文档 删除文档
批量导入文档 es索引库操作
索引库类似于数据库中的表mapping(映射)相当于表的结构
因此我们要向es存储数据时必须先创建索引库和mapping(映射)
mapping映射操作
mapping是对索引库中文档的约束常见的mapping属性有 1.type:字段数据类型常见的简单类型有 字符串text(可分词文本)keyword(精确词不可进行分词) 数值integer,long,short,byte,double,float 布尔值:boolean 日期:date 对象:object 2.index:是否为这个字段创建索引默认为true 3.analyzer:这个字段使用哪种分词器前提为type类型的text可分词文本 4.properties:该字段的子字段 例如下面的json文档
{age: 21,weight: 52.1,isMarried: false,info: 我是最厉害的,email: zyitcast.cn,score: [99.1, 99.5, 98.9],name: {firstName: 云,lastName: 赵}
} 对应的每个字段映射mapping age类型为 integer参与搜索因此需要index为true无需分词器weight类型为float参与搜索因此需要index为true无需分词器isMarried类型为boolean参与搜索因此需要index为true无需分词器info类型为字符串需要分词因此是text参与搜索因此需要index为true分词器可以用ik_smartemail类型为字符串但是不需要分词因此是keyword不参与搜索因此需要index为false无需分词器score虽然是数组但是我们只看元素的类型类型为float参与搜索因此需要index为true无需分词器name类型为object需要定义多个子属性 name.firstName类型为字符串但是不需要分词因此是keyword参与搜索因此需要index为true无需分词器name.lastName类型为字符串但是不需要分词因此是keyword参与搜索因此需要index为true无需分词器 索引库的CURD操作
这里我们使用Kibana编写DSL的方式来演示。
1.创建索引库和映射
基本语法
请求方式PUT请求路径/索引库名可以自定义请求参数mapping映射 2.查询索引库
基本语法 请求方式GET 请求路径/索引库名 请求参数无 GET /person 3.删除索引库
语法 请求方式DELETE 请求路径/索引库名 请求参数无 DELETE /person 查询不到person索引库 4.修改索引库
倒排索引结构虽然不复杂但是一旦数据结构改变比如改变了分词器就需要重新创建倒排索引这简直是灾难。因此索引库一旦创建无法修改mapping。
虽然无法修改mapping中已有的字段但是却允许添加新的字段到mapping中因为不会对倒排索引产生影响。 再次查询birthday字段已经添加成功 5.总结
索引库操作有哪些
创建索引库PUT /索引库名查询索引库GET /索引库名删除索引库DELETE /索引库名添加字段PUT /索引库名/_mapping 文档的CURD操作
我们在数据库中创建了一张数据表和表的结构后是不是要开始向表中插入数据了。
在索引库中也是这样我们已经创建了索引库并设置了mapping(映射)现在我们要向索引库中插入文档数据
1.新增文档
语法
POST /索引库名/_doc/文档id
{字段1: 值1,字段2: 值2,字段3: {子属性1: 值3,子属性2: 值4},// ...
} 显示创建成功即增加成功 2.查询文档
根据rest风格新增是post查询应该是get不过查询一般都需要条件这里我们把文档id带上。
语法
GET /{索引库名称}/_doc/{id}
例子
#查询索引库的id为1的文档
GET /person/_doc/1 3.删除文档
删除使用DELETE请求同样需要根据id进行删除
语法
DELETE /{索引库名}/_doc/id值 例子
DELETE /person/_doc/1
4.修改文档
修改有两种方式
全量修改直接覆盖原来的文档增量修改修改文档中的部分字段
全量修改
全量修改是覆盖原来的文档其本质是
先根据指定的id删除文档再新增一个相同id的文档
注意如果根据id删除时id不存在第二步的新增也会执行也就从修改变成了新增操作了。
语法
PUT /{索引库名}/_doc/文档id
{字段1: 值1,字段2: 值2,// ... 略
} 增量修改
增量修改是只修改指定id匹配的文档中的部分字段。 语法
POST /{索引库名}/_update/文档id
{doc: {字段名: 新的值,}
}
例子修改姓名
#增量修改
POST /person/_update/1
{doc:{name:{lastName:何}}
} 5.总结
文档操作有哪些
创建文档POST /{索引库名}/_doc/文档id { json文档 }查询文档GET /{索引库名}/_doc/文档id删除文档DELETE /{索引库名}/_doc/文档id修改文档 全量修改PUT /{索引库名}/_doc/文档id { json文档 }增量修改POST /{索引库名}/_update/文档id { doc: {字段}}
RestAPI
ES官方提供了各种不同语言的客户端用来操作ES。这些客户端的本质就是组装DSL语句通过http请求发送给ES。官方文档地址Elasticsearch Clients | Elastic
其中的Java Rest Client又包括两种
Java Low Level Rest ClientJava High Level Rest Client
这里使用的是Java HighLevel Rest Client客户端API
使用API例子
需要的数据库表结构
CREATE TABLE tb_hotel (id bigint(20) NOT NULL COMMENT 酒店id,name varchar(255) NOT NULL COMMENT 酒店名称例7天酒店,address varchar(255) NOT NULL COMMENT 酒店地址例航头路,price int(10) NOT NULL COMMENT 酒店价格例329,score int(2) NOT NULL COMMENT 酒店评分例45就是4.5分,brand varchar(32) NOT NULL COMMENT 酒店品牌例如家,city varchar(32) NOT NULL COMMENT 所在城市例上海,star_name varchar(16) DEFAULT NULL COMMENT 酒店星级从低到高分别是1星到5星1钻到5钻,business varchar(255) DEFAULT NULL COMMENT 商圈例虹桥,latitude varchar(32) NOT NULL COMMENT 纬度例31.2497,longitude varchar(32) NOT NULL COMMENT 经度例120.3925,pic varchar(255) DEFAULT NULL COMMENT 酒店图片例:/img/1.jpg,PRIMARY KEY (id)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4; 分析这个数据表的结构然后构建索引库和mapping
创建索引库最关键的是mapping映射而mapping映射要考虑的信息包括
字段名字段数据类型是否参与搜索(是否需要index索引)是否需要分词如果分词分词器是什么
其中
字段名、字段数据类型可以参考数据表结构的名称和类型是否参与搜索要分析业务来判断例如图片地址就无需参与搜索是否分词呢要看内容内容如果是一个整体就无需分词反之则要分词分词器我们可以统一使用ik_max_word
这是分析出来的索引库结构
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}}}
} 索引库结构说明
这里将name,brand,city字段都使用了mapping的copy_to属性复制到了all字段。
复制的原因是我们并不知道用户进行搜索时是根据酒店的名字还是品牌还是城市进行搜索的如果在三个字段中进行匹配搜索对es的开销十分大所以我们把这三个字段合并成一个all字段这样一来用户进行搜索时我们只需要在all字段进行文档匹配获取对应的id即可 但是对每个字段的是否分词还是原来的形式如name进行最细分词brand,city都不进行分词
这里设置了location字段它的type类型是geo_point类型这是es提供的包括了维度精度的数据类型 初始化RestClient
在elasticsearch提供的API中与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中必须先完成这个对象的初始化建立与elasticsearch的连接。
1.导入es的RestHighLevelClient依赖
dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactId
/dependency
2.因为SpringBoot默认的ES版本是7.6.2所以我们需要覆盖默认的ES版本换成自己的es版本
propertiesjava.version1.8/java.versionelasticsearch.version7.12.1/elasticsearch.version
/properties 3.初始化RestHighLevelClient即维护一个bean到IoC容器 //定义操作es的客户端对象Beanpublic RestHighLevelClient restHighLevelClient(){return new RestHighLevelClient(RestClient.builder(HttpHost.create(http://192.168.230.100:9200)));}
使用RestHighLevelClient构建索引库及其mapping
代码分为三步
1创建Request对象。因为是创建索引库的操作因此Request是CreateIndexRequest。2添加请求参数其实就是DSL的JSON参数部分。因为json字符串很长这里是定义了静态字符串常量HOTEL_MAPPING让代码看起来更加优雅。3发送请求client.indices()方法的返回值是IndicesClient类型封装了所有与索引库操作有关的方法。
1.构建json数据常量
public class HotelConstant {public static final String HOTEL_MAPPING{\n \mappings\: {\n \properties\: {\n \id\: {\n \type\: \keyword\\n },\n \name\:{\n \type\: \text\,\n \analyzer\: \ik_max_word\,\n \copy_to\: \all\\n },\n \address\:{\n \type\: \keyword\,\n \index\: false\n },\n \price\:{\n \type\: \integer\\n },\n \score\:{\n \type\: \integer\\n },\n \brand\:{\n \type\: \keyword\,\n \copy_to\: \all\\n },\n \city\:{\n \type\: \keyword\,\n \copy_to\: \all\\n },\n \starName\:{\n \type\: \keyword\\n },\n \business\:{\n \type\: \keyword\\n },\n \location\:{\n \type\: \geo_point\\n },\n \pic\:{\n \type\: \keyword\,\n \index\: false\n },\n \all\:{\n \type\: \text\,\n \analyzer\: \ik_max_word\\n }\n }\n }\n };
}2.创建索引库
/*** 测试索引库功能*/
SpringBootTest
public class TestIndex {Autowiredprivate RestHighLevelClient restHighLevelClient;Testpublic void test01() throws IOException {//构建 创建索引库请求对象参数为索引库对象CreateIndexRequest request new CreateIndexRequest(hotel);//设置DSL语句,第一个参数为构建mapping的json语句第二个参数是表明这是JSON数据格式request.source(HotelConstant.HOTEL_MAPPING, XContentType.JSON);//发起请求CreateIndexResponse result restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);boolean isSuccess result.isAcknowledged();System.out.println(isSuccess?构建索引库成功:构建索引库失败);}
} 3.测试是否构建成功 GET /hotel 使用RestHighLevelClient查询索引库和删除索引库 /*** 判断索引库是否存在*/Testpublic void test02() throws IOException {//构建 获取索引库请求对象参数为索引库名字GetIndexRequest request new GetIndexRequest(hotel);//查询不用写dsl语句//直接发起请求,判断索引库是否存在boolean exists restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);System.out.println(exists?hotel索引库存在:hotel索引库不存在);}/*** 删除索引库*/Testpublic void test03() throws IOException {//构建 删除索引库请求对象参数为索引库对象DeleteIndexRequest request new DeleteIndexRequest(hotel);//删除不用写dsl语句//直接发起请求删除索引库AcknowledgedResponse result restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);boolean isSuccess result.isAcknowledged();System.out.println(isSuccess?删除成功:删除失败);}
总结
JavaRestClient操作elasticsearch的流程基本类似。核心是restHignLevelClient.indices()方法来获取索引库的操作对象。
索引库操作的基本步骤
初始化RestHighLevelClient创建XxxIndexRequest。XXX是Create、Get、Delete准备DSL Create时需要其它是无参发送请求。调用RestHighLevelClient.indices().xxx()方法xxx是create、exists、delete RestClient操作文档
新增文档
我们要将数据库的酒店数据查询出来写入elasticsearch中。
构建索引库实体类
数据库查询后的结果是一个Hotel类型的对象。结构如下
Data
TableName(tb_hotel)
public class Hotel {TableId(type IdType.INPUT)private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String longitude;private String latitude;private String pic;
}
与我们的索引库结构存在差异
longitude和latitude需要合并为location
因此我们需要定义一个新的类型与索引库结构吻合
Data
NoArgsConstructor
public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;public HotelDoc(Hotel hotel) {this.id hotel.getId();this.name hotel.getName();this.address hotel.getAddress();this.price hotel.getPrice();this.score hotel.getScore();this.brand hotel.getBrand();this.city hotel.getCity();this.starName hotel.getStarName();this.business hotel.getBusiness();this.location hotel.getLatitude() , hotel.getLongitude();this.pic hotel.getPic();}
} 新增文档的DSL语句如下
POST /{索引库名}/_doc/1
{name: Jack,age: 21
} 代码实现
SpringBootTest
public class TestDoc {Autowiredprivate HotelMapper hotelMapper;Autowiredprivate RestHighLevelClient restHighLevelClient;Testpublic void test01() throws IOException {//使用mapper去数据库中查询数据Hotel hotel hotelMapper.selectById(36934L);//封装成HotelDoc类HotelDoc hotelDoc new HotelDoc(hotel);//序列化成json数据,当作DSL语句String jsonDSL JSON.toJSONString(hotelDoc);//构建 文档请求对象第一个参数是索引库名字第二个是文档idIndexRequest request new IndexRequest(hotel).id(hotelDoc.getId());//设置DSL语句request.source(jsonDSL, XContentType.JSON);//发送请求IndexResponse result restHighLevelClient.index(request, RequestOptions.DEFAULT);System.out.println(result);}
}测试 GET /hotel/_doc/36934 /*** 获取文档信息*/Testpublic void test02() throws IOException {//构建 查询文档请求对象GetRequest request new GetRequest(hotel, 36934);//查询不用写DSL语句//直接发送请求GetResponse response restHighLevelClient.get(request, RequestOptions.DEFAULT);//获取响应的json数据String jsonData response.getSourceAsString();//将json数据反序列化成对象HotelDoc hotelDoc JSON.parseObject(jsonData, HotelDoc.class);System.out.println(hotelDoc);} 查询文档
查询的DSL语句如下
GET /hotel/_doc/{id} /*** 获取文档信息*/Testpublic void test02() throws IOException {//构建 查询文档请求对象GetRequest request new GetRequest(hotel, 36934);//查询不用写DSL语句//直接发送请求GetResponse response restHighLevelClient.get(request, RequestOptions.DEFAULT);//获取响应的json数据String jsonData response.getSourceAsString();//将json数据反序列化成对象HotelDoc hotelDoc JSON.parseObject(jsonData, HotelDoc.class);System.out.println(hotelDoc);}
修改文档
修改我们讲过两种方式
全量修改本质是先根据id删除再新增增量修改修改文档中的指定字段值
在RestClient的API中全量修改与新增的API完全一致判断依据是ID
如果新增时ID已经存在则修改如果新增时ID不存在则新增
所以我们主要关注增量修改。
与之前类似也是三步走
1准备Request对象。这次是修改所以是UpdateRequest2准备参数。也就是JSON文档里面包含要修改的字段3更新文档。这里调用client.update()方法 /*** 增量修改文档的部分信息*/Testpublic void test03() throws IOException {//构建 更新文档的请求对象UpdateRequest request new UpdateRequest(hotel, 36934);//编写DSL语句request.doc(city,天津);//发送请求UpdateResponse response restHighLevelClient.update(request, RequestOptions.DEFAULT);} 删除文档 /*** 删除文档*/Testpublic void test04() throws IOException {//构建 删除文档请求对象DeleteRequest request new DeleteRequest(hotel, 36934);//直接发送请求restHighLevelClient.delete(request,RequestOptions.DEFAULT);}
批量导入文档
案例需求利用BulkRequest批量将数据库数据导入到索引库中。
步骤如下 利用mybatis-plus查询酒店数据 将查询到的酒店数据Hotel转换为文档类型数据HotelDoc 利用JavaRestClient中的BulkRequest批处理实现批量新增文档 /*** 批量导入数据*/Testpublic void test05() throws IOException {//使用mapper查询到所有数据ListHotel hotels hotelMapper.selectList(null);BulkRequest bulkRequest new BulkRequest(hotel);hotels.stream().forEach(hotel - {//把hotel变成hotelDoc类对象并序列化成json数据String jsonDSL JSON.toJSONString(new HotelDoc(hotel));//构建 新增文档请求对象IndexRequest request new IndexRequest(hotel).id(hotel.getId()).source(jsonDSL, XContentType.JSON);//将请求对象添加到bulkRequest中bulkRequest.add(request);});//发送请求restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);}
成功导入es GET /hotel/_search { query: { match_all: {} } }