微服务—DSL基础语法与RestClient操作

本博客为个人学习笔记,学习网站:黑马程序员SpringCloud 2021教程

目录

DSL语法

索引库操作

mapping属性

创建索引库

 字段拷贝 

查询、删除、修改索引库

文档操作

新增文档

查询、删除文档

修改文档

全量修改

增量修改

DSL文档语法小结

RestClient操作

初始化RestClient

索引库操作

RestClient创建索引库

RestClient删除索引库

RestClient判断索引库是否存在

文档操作

RestClient新增文档

RestClient查询文档

RestClient修改文档

全量修改

增量修改

RestClient删除文档

RestClient批量新增文档

RestClient文档操作小结


DSL语法

索引库操作

mapping属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

1. type:字段数据类型,常见的简单类型有:
        字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址、分词无意义的值)
        数值:long、integer、short、byte、double、float
        布尔:boolean
        日期:date
        对象:object

2. index:是否创建索引,默认为true

3. analyzer:使用哪种分词器

4. properties:该字段的子字段


创建索引库

示例 :
按以下json文档的字段创建一个索引库

{
    "age": 21,
    "weight": 52.1,
    "isMarried": false,
    "info": "黑马程序员Java讲师",
    "email": "zy@itcast.cn",
    "score": [99.1, 99.5, 98.9],
    "name": {
        "firstName": "云",
        "lastName": "赵"
    }
}

创建索引库DSL语句如下

# 创建索引库
PUT /heima
{
  "mappings": {
    "properties": {
      "info":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "email":{
        "type": "keyword",
        "index": false
      },
      "name":{
        "type": "object",
        "properties": {
          "firstName":{
            "type": "keyword"
          },
          "lastName":{
            "type":"keyword"
          }
        }
      }
    }
  }
}

 字段拷贝 

如果在查询文档时,想要同时基于多个字段进行查询,那么在创建索引库时,可以把这些字段通过"copy_to"拷贝到另外一个字段all中,在之后的搜索中,直接搜索all字段即可。而且,all字段在查询得到的结果文档中是不会显示出来的,但是在查询的时候,会提示可以查询all字段。


查询、删除、修改索引库

查询索引库:

#语法
GET /索引库名

#示例如下
GET /heima

 删除索引库:

#语法如下
DELETE /索引库名

#示例如下
DELETE /heima

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

新增字段:

#语法如下
PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

#示例如下(新字段名必须和存在的字段名不同)
PUT /heima/_mapping
{
  "properties":{
    "age":{
      "type":"long"
    }
  }
}

文档操作

新增文档

#语法如下
POST /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    "字段3": {
        "子属性1": "值3",
        "子属性2": "值4"
    },
    // ...
}

#示例如下
POST /heima/_doc/1
{
    "info": "黑马程序员Java讲师",
    "email": "zy@itcast.cn",
    "name": {
        "firstName": "云",
        "lastName": "赵"
    }
}

查询、删除文档

查询文档:

#语法如下
GET /{索引库名称}/_doc/{id}

#示例如下
GET /heima/_doc/1

删除文档:

#语法如下
DELETE /{索引库名}/_doc/id值

#示例如下(根据id删除文档)
DELETE /heima/_doc/1

修改文档

修改文档有两种方式:
1. 全量修改:直接覆盖原来的文档
2. 增量修改:修改文档中的部分字段 

全量修改

全量修改是覆盖原来的文档,其本质是:先根据指定的id删除文档,再新增一个相同id的文档
注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。

#语法如下
PUT /{索引库名}/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    // ... 略
}

#示例如下
PUT /heima/_doc/1
{
    "info": "黑马程序员高级Java讲师",
    "email": "zy@itcast.cn",
    "name": {
        "firstName": "云",
        "lastName": "赵"
    }
}

增量修改

增量修改是只修改指定id匹配的文档中的部分字段。

#语法如下
POST /{索引库名}/_update/文档id
{
    "doc": {
         "字段名": "新的值",
    }
}

#示例如下
POST /heima/_update/1
{
  "doc": {
    "email": "ZhaoYun@itcast.cn"
  }
}

DSL文档语法小结

创建文档:POST/(索引库名}/_doc/文档id {json文档}
查询文档:GET /(索引库名}/_doc/文档id
删除文档:DELETE /(索引库名}/_doc/文档id
修改文档:
        全量修改:PUT /(索引库名}/doc/文档id {json文档 }
        增量修改:POST/{索引库名}/_update/文档id {“doc":{字段}}


RestClient操作

初始化RestClient

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

步骤1. 引入es的RestHighLevelClient依赖:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

步骤2. 因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

<properties>
    <java.version>1.8</java.version>
    <elasticsearch.version>7.12.1</elasticsearch.version>
</properties>

步骤3. 初始化RestHighLevelClient,代码如下:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        HttpHost.create("http://192.168.150.101:9200")
));

步骤4. 这里为了单元测试方便,我们创建一个测试类HotelIndexTest,然后将初始化的代码编写在@BeforeEach方法中:

package cn.itcast.hotel;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;

public class HotelIndexTest {
    private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.150.101:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

索引库操作

RestClient创建索引库

代码如下: 

@Test
void createHotelIndex() throws IOException {
    // 1.创建Request对象
    CreateIndexRequest request = new CreateIndexRequest("hotel");
    // 2.准备请求的参数:DSL语句
    request.source(MAPPING_TEMPLATE, XContentType.JSON);
    // 3.发送请求
    client.indices().create(request, RequestOptions.DEFAULT);
}

RestClient删除索引库

@Test
void testDeleteHotelIndex() throws IOException {
    // 1.创建Request对象
    DeleteIndexRequest request = new DeleteIndexRequest("hotel");
    // 2.发送请求
    client.indices().delete(request, RequestOptions.DEFAULT);
}

RestClient判断索引库是否存在

@Test
void testExistsHotelIndex() throws IOException {
    // 1.创建Request对象
    GetIndexRequest request = new GetIndexRequest("hotel");
    // 2.发送请求
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    // 3.输出
    System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}

文档操作

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;
}

由于该对象的结构与elasticsearch索引库结构存在差异,因此我们需要定义一个新的类型,与索引库结构吻合,结构如下:

package cn.itcast.hotel.pojo;

import lombok.Data;
import lombok.NoArgsConstructor;

@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();
    }
}

新增文档语法: 

从数据库中查询数据,并新增到ES文档实现:

@Test
void testAddDocument() throws IOException {
    // 1.根据id查询酒店数据
    Hotel hotel = hotelService.getById(61083L);
    // 2.转换为文档类型
    HotelDoc hotelDoc = new HotelDoc(hotel);
    // 3.将HotelDoc转json
    String json = JSON.toJSONString(hotelDoc);

    // 1.准备Request对象
    IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
    // 2.准备Json文档
    request.source(json, XContentType.JSON);
    // 3.发送请求
    client.index(request, RequestOptions.DEFAULT);
}

RestClient查询文档

查询语法:

代码如下: 

@Test
void testGetDocumentById() throws IOException {
    // 1.准备Request
    GetRequest request = new GetRequest("hotel", "61082");
    // 2.发送请求,得到响应
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    // 3.解析响应结果
    String json = response.getSourceAsString();

    HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
    System.out.println(hotelDoc);
}

RestClient修改文档

在DSL语法中,我们讲过修改文档的两种方式:
1. 全量修改:本质是先根据id删除,再新增
2. 增量修改:修改文档中的指定字段值

全量修改

在Restclient的API中,全量修改与新增的API完全一致,判断依据是ID:
如果新增时,ID已存在,则修改;
如果新增时,ID不存在,则新增。
全量修改的语法这里不再赘述,参考前面的新增文档即可,这里我们主要关注增量修改。


增量修改

增量修改语法如下:

代码如下:

@Test
void testUpdateDocument() throws IOException {
    // 1.准备Request
    UpdateRequest request = new UpdateRequest("hotel", "61083");
    // 2.准备请求参数
    request.doc(
        "price", "952",
        "starName", "四钻"
    );
    // 3.发送请求
    client.update(request, RequestOptions.DEFAULT);
}

RestClient删除文档

根据id删除文档,代码如下:

@Test
void testDeleteDocument() throws IOException {
    // 1.准备Request
    DeleteRequest request = new DeleteRequest("hotel", "61083");
    // 2.发送请求
    client.delete(request, RequestOptions.DEFAULT);
}

RestClient批量新增文档

利用BulkRequest实现批量操作,其本质就是将多个普通的CRUD请求组合在一起发送。

其中提供了一个add方法,我们可以把IndexRequest(新增)、UpdateRequest(修改)、DeleteRequest(删除) 通过add方法进行添加,从而实现批量操作。

示例: 

利用MP从数据库获取数据,并批量新增完整代码: 

@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);
}

RestClient文档操作小结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/391532.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JWT登录验证前后端设计与实现笔记

设计内容 前端 配置全局前置路由守卫axios拦截器登录页面和主页 后端 JWT的封装登录接口中间件放行mysql数据库的连接 详细设计 路由设计 配置全局前置守卫&#xff0c;如果访问的是登录页面则放行&#xff0c;不是则进入判断是否有token&#xff0c;没有则拦截回到登录…

17-k8s控制器资源-job控制

job控制器&#xff1a;就是一次性任务的pod控制器&#xff0c;pod完成作业后不会重启&#xff0c;其重启策略是&#xff1a;Never 1&#xff0c;job控制器案例描述 启动一个pod&#xff0c;执行完成一个事件&#xff0c;然后pod关闭&#xff1b; 事件&#xff1a;计算π的值&a…

[java基础揉碎]类与对象

目录 类与对象的引出: 类与对象的概述: 类与对象在内存中的布局: 属性的注意细节: 类与对象在内存中创建的过程: 类与对象的引出: 例如这样一个问题: 如果用单独变量来解决, 就会有一个问题, 不利于数据的管理, 将所有猫的信息都给拆解了: 如果用数组来解决, 则会有 1)数…

第三百五十回

文章目录 1. 概要介绍2. 获取方法2.1 获取语言2.2 获取地址 3.示例代码3. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题"相关的内容&#xff0c;本章回中将介绍如何获取系统语言.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概要介绍 我们在本…

书生浦语-模型微调

大语言模型微调 指令微调的流程 LoRA(旁路分支微调) Xtuner微调框架 微调训练 作业 微调作业需要多训练几个epoch&#xff0c;这里训练了16个epoch

141 . 环形链表

链接 https://leetcode.cn/problems/linked-list-cycle/description/?envTypestudy-plan-v2&envIdtop-interview-150 题面 思路 : 法1 &#xff1a; 用哈希表来存之前的遍历过的结点 ; 一遍遍历&#xff0c;在遍历的过程中&#xff0c;先判断是否当前结点在哈希表…

【Redis实战】有MQ为啥不用?用Redis作消息队列!?Redis作消息队列使用方法及底层原理高级进阶

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Redis实战与进阶》 本专栏纯属为爱发电永久免费&#xff01;&a…

IDEA配置Lombok不起作用

IDEA配置Lombok不起作用 我们通常会只用lombok来简化代码。但是使用IDEA的lombok插件时&#xff0c;Lombok并不起作用。 可以按照如下操作。 FIle -> settings ->build,excecution,deployment–>compiler–>annotation processors勾选上 enable annotation proc…

ubuntu22.04安装jenkins并配置

准备 更新系统 sudo apt update sudo apt upgrade环境准备 jdk 安装 sudo apt install openjdk-11-jdk验证 java -versiongit ubuntu配置git maven ubuntu配置maven 部署 添加 Jenkins 存储库 导入Jenkins存储库的GPG密钥 wget -q -O - https://pkg.jenkins.io/de…

什么是PAGA系统

PAGA系统是一种公共广播和通用报警系统&#xff0c;它在船舶、海上钻井平台、石油化工、天然气开采等行业的应用非常广泛。当遇到紧急情况或其他特殊情况时&#xff0c;PAGA系统能够在大范围内进行喊话广播或报警。这种系统通过自动电话系统&#xff08;如PABX&#xff0c;即自…

Unity 2D Spine 外发光实现思路

Unity 2D Spine 外发光实现思路 前言 对于3D骨骼&#xff0c;要做外发光可以之间通过向法线方向延申来实现。 但是对于2D骨骼&#xff0c;各顶点的法线没有向3D骨骼那样拥有垂直于面的特性&#xff0c;那我们如何做2D骨骼的外发光效果呢&#xff1f; 理论基础 我们要知道&a…

前端小案例——购买电影票(HTML+CSS+JS, 附源码)

一、前言 实现功能&#xff1a; 这段代码实现了一个简单的电影票选座购买的功能界面。 在页面上展示了一个电影院的座位布局&#xff0c;以及右侧显示了电影信息、选座情况、票价、总计等内容。 用户可以通过点击座位来选择购买电影票&#xff0c;每个座位的状态会在点击时改…

Arrays工具类的常见方法总结

一、Arrays.asList( ) 1、作用 Arrays.asList( )可以将一个数组以集合的形式传入一个集合对象。通常用来将一组元素全部添加到集合中。 2、参数及返回值 参数&#xff1a;一组动态参数 返回值&#xff1a;List<T>集合 3、应用举例 List<String> boyListArra…

2023年程序员观察报告

春节假期已过&#xff0c;2023年悄然过去&#xff0c;2024年已经到来&#xff0c;无论2023年是快乐的、成长的、积极的&#xff0c;亦或是痛苦的、寂寥的、迷茫的&#xff0c;都要恭喜在座的各位程序员又熬过了一年&#xff01; ①加班篇 2023年&#xff0c;你完成了 132个需求…

you-get,一个超强的 Python 库

你好&#xff0c;我是坚持分享干货的 EarlGrey&#xff0c;翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助&#xff0c;请关注我&#xff0c;一起向上进击。 现在在线视频超火爆&#xff0c;可是我还是更倾向于将视频下载至本地…

C++-手把手教你模拟实现string

1.string的成员变量 模拟实现string只需要三个成员变量&#xff0c;capacity&#xff0c;size&#xff0c;_str&#xff0c;也就是容量&#xff0c;数据大小&#xff0c;指向字符串的指针。 2.string的构造函数 2.1 使用字符串构造 使用字符串来构造一个string类的对象&…

463. Island Perimeter(岛屿的周长)

问题描述 给定一个 row x col 的二维网格地图 grid &#xff0c;其中&#xff1a;grid[i][j] 1 表示陆地&#xff0c; grid[i][j] 0 表示水域。 网格中的格子 水平和垂直 方向相连&#xff08;对角线方向不相连&#xff09;。整个网格被水完全包围&#xff0c;但其中恰好有…

LTP/pyltp安装和使用教程

文章目录 LTP介绍分句分词加载外部词典个性化分词 词性标注命名实体识别NER依存句法分析语义角色标注 LTP介绍 官网&#xff1a;https://ltp.ai/ 下载可以到官网的下载专区&#xff1a;https://ltp.ai/download.html 语言技术平台&#xff08;Language Technology Platform&am…

Codeforces Round 925 (Div. 3)(A,B,C,D,E,F,G)

比赛链接 这场打的很顺&#xff0c;感觉难度和 div 4 差不多&#xff0c;不是很难。D题稍微考了考同余的性质&#xff0c;E题直接模拟过程即可&#xff0c;F题也可以暴力模拟或者拓扑排序&#xff0c;G题是个数学题&#xff0c;是个简单隔板法。A到F题都可以直接模拟就有点离谱…