【微服务】Elasticsearch文档索引库操作(二)
🚗Es学习·第二站~
🚩Es学习起始站:【微服务】Elasticsearch概述&环境搭建(一)
🚩本文已收录至专栏:微服务探索之旅
👍希望您能有所收获
一.索引库操作
索引库就类似数据库表,mapping映射就类似表的结构。我们要向es中存储数据,必须先创建“库”和“表”。
(1) mapping映射属性
mapping是对索引库中文档的约束,常见的mapping属性包括:
type
:字段数据类型,常见的简单类型有:- 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
- 数值:long、integer、short、byte、double、float、
- 布尔:boolean
- 日期:date
- 对象:object
index
:是否创建倒排索引(字段能否被搜索),默认为trueanalyzer
:使用哪种分词器,一般只有text类型需要使用properties
:指定字段的子字段
例如下面的json文档:
{"age": 21,"weight": 52.1,"isMarried": false,"info": "观止BlogNote","email": "zx@guanzhi.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_smart
- email:类型为字符串,但是不需要分词,因此是keyword;不参与搜索,index应为false;无需分词器
- score:虽然看起来是数组,但是我们只看其中元素的类型,类型为float;参与搜索,index应为true;无需分词器
- name:类型为object,需要定义多个子属性
- name.firstName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,index应为true;无需分词器
- name.lastName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,index应为true;无需分词器
(2) 索引库的CRUD
这里我们先统一使用Kibana编写DSL的方式来演示,随后再在Java中操作演示。
(2.1) 创建索引库和映射
(2.1.1) 基本语法
-
请求方式:PUT
-
请求路径:/索引库名,可以自定义
-
请求参数:mapping映射
格式:
PUT /索引库名称
{"mappings": {"properties": {"字段名":{"type": "数据类型","analyzer": "分词器"},"字段名2":{"type": "数据类型","index": boolean值},"字段名3":{"properties": {"子字段": {"type": "数据类型"}}},// ...略}}
}
(2.1.2) 示例代码
PUT /guanzhi
{"mappings": {"properties": {"info": {"type": "text","analyzer": "ik_smart"},"email": {"type": "keyword","index": false},"name": {"type": "object","properties": {"firstName": {"type": "keyword"},"lastName":{"type": "keyword"}}}// ...略}}
}
(2.2) 查询索引库
(2.2.1) 基本语法
-
请求方式:GET
-
请求路径:/索引库名
-
请求参数:无
格式:
GET /索引库名
(2.2.2) 示例代码
GET /guanzhi
(2.3) 修改索引库
(2.3.1) 说明
倒排索引结构虽然不复杂,但是一旦数据结构改变(比如改变了分词器),就需要重新创建倒排索引。因此索引库一旦创建,无法修改mapping中已有的字段,但是却允许添加新的字段到mapping中,因为不会对倒排索引产生影响。
(2.3.2) 基本语法
-
请求方式:PUT
-
请求路径:/索引库名/_mapping,可以自定义
-
请求参数:mapping映射
格式:
PUT /索引库名/_mapping
{"properties": {"新字段名":{"type": "数据类型"}}
}
(2.3.3) 示例代码
PUT /guanzhi/_mapping
{"properties": {"age":{"type": "integer"}}
}
(2.4) 删除索引库
(2.4.1) 基本语法
-
请求方式:DELETE
-
请求路径:/索引库名
-
请求参数:无
格式:
DELETE /索引库名
(2.4.2) 示例代码
DELETE /guanzhi
二.文档操作
上述我们已经学会了如何创建索引库,接下来让我们一起在索引库中操作数据。
(1) 新增文档
(1.1) 基本语法
-
请求方式:POST
-
请求路径:/索引库名/_doc/文档id
-
请求参数:json文档
格式:
POST /索引库名/_doc/文档id
{"字段1": "值1","字段2": "值2","字段3": {"子属性1": "值3","子属性2": "值4"},// ...
}
(1.2) 示例代码
POST /guanzhi/_doc/1
{"info": "观止BlogNote","email": "zy@guanzhi.cn","name": {"firstName": "止","lastName": "观"}
}
(2) 查询文档
(2.1) 基本语法
-
请求方式:GET
-
请求路径:/索引库名称/_doc/文档id
-
请求参数:无
语法:
GET /索引库名称/_doc/文档id
(2.2) 示例代码
GET /guanzhi/_doc/1
(3) 删除文档
(3.1) 基本语法
-
请求方式:DELETE
-
请求路径:/索引库名/_doc/文档id
-
请求参数:无
语法:
DELETE /索引库名/_doc/文档id
(3.2) 示例代码
# 根据id删除数据
DELETE /guanzhi/_doc/1
(4) 修改文档
修改有两种方式:
- 全量修改:会删除旧文档,添加新文档
- 增量修改:指定修改文档中的部分字段
(4.1) 全量修改
(4.1.1) 概述
全量修改是覆盖原来的文档,其本质是:
- 根据指定的id删除文档
- 新增一个相同id的文档
注意:如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。
(4.1.2) 基本语法
-
请求方式:PUT
-
请求路径:/索引库名/_doc/文档id
-
请求参数:json文档
语法:
PUT /索引库名/_doc/文档id
{"字段1": "值1","字段2": "值2",// ... 略
}
(4.1.3) 示例代码
PUT /guanzhi/_doc/1
{"info": "观止BlogNote","email": "zy@guan.cn","name": {"firstName": "止","lastName": "观"}
}
(4.2) 增量修改
增量修改是只修改指定id匹配的文档中的部分字段。
(4.2.1) 基本语法
-
请求方式:POST
-
请求路径:/索引库名/_update/文档id
-
请求参数:json文档
语法:
POST /索引库名/_update/文档id
{"doc": {"字段名": "新的值",}
}
(4.2.2) 示例代码
POST /guanzhi/_update/1
{"doc": {"info": "观止Note",}
}
三.RestAPI操作
ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。接下来我们学习的是Java HighLevel Rest Client客户端API,一起使用Java代码操作Es。
高版本Es请跳过如下教程~
注:在Es7.15版本之后,Es官方将它的高级客户端RestHighLevelClient标记为弃用状态。同时推出了全新的Java API客户端Elasticsearch Java API Client,该客户端也将在Es8.0及以后版本中成为官方推荐使用的客户端。
(1) 环境搭建
(1.1) 导入数据
链接:https://pan.baidu.com/s/1eSlsQ6ypaDNkqXO75mC6IA
提取码:3yzw
首先运行资料中的sql文件:
数据结构如下:
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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
(1.2) 导入项目
然后导入资料提供的项目:
项目结构如图:
(1.3) 导入依赖
- 引入es的RestHighLevelClient依赖:
<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>
(1.4) 初始化RestClient
在es提供的API中,与es一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。
- 初始化RestHighLevelClient:
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")
));
- 为了单元测试方便,我们创建一个测试类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;// 初始化代码,建立连接@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")));}// CRUD操作.....// 结束代码@AfterEachvoid tearDown() throws IOException {this.client.close();}
}
(2) RestClient操作索引库
(2.1) 创建索引库
(2.1.1) 分析映射
创建索引库,最关键的是分析mapping映射,而mapping映射要考虑的信息包括:
- 字段名
- 字段数据类型
- 是否参与搜索
- 是否需要分词
- 如果分词,分词器是什么?
其中:
- 字段名、字段数据类型,可以参考数据表结构的名称和类型
- 是否参与搜索要分析业务来判断,例如图片地址,就无需参与搜索
- 是否分词呢要看内容,内容如果是一个整体就无需分词,反之则要分词
- 分词器,我们可以统一使用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"}}}
}
几个特殊字段说明:
- location:地理坐标,里面包含精度、纬度
- all:一个组合字段,其目的是将多字段的值 利用copy_to合并,提供给用户搜索
地理坐标说明:
copy_to说明,让Es对单个字段进行搜索,提高搜索效率:
(2.1.2) Java操作
创建索引库的API如下:
-
代码分为三步:
-
创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。
-
添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。
-
发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。
-
- 创建一个constants常量类,定义上述mapping映射的JSON字符串常量:
package cn.itcast.hotel.constants;public class HotelConstants {public static final String MAPPING_TEMPLATE = "{\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" +"}";
}
- 在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现创建索引:
@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);
}
(2.2) 删除索引库
删除索引库操作非常简单,与创建索引库之间代码的差异,注意体现在Request对象上。依然是三步走:
- 创建Request对象。这次是DeleteIndexRequest对象
- 发送请求。改用delete方法
在hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现删除索引:
@Test
void testDeleteHotelIndex() throws IOException {// 1.创建Request对象DeleteIndexRequest request = new DeleteIndexRequest("hotel");// 2.发送请求client.indices().delete(request, RequestOptions.DEFAULT);
}
(2.3) 判断索引库是否存在
判断索引库是否存在,本质就是查询,对应的DSL是:
GET /hotel
因此与删除的Java代码流程是类似的。依然是三步走:
- 创建Request对象。这次是GetIndexRequest对象
- 发送请求。改用exists方法
@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 ? "索引库已经存在!" : "索引库不存在!");
}
(2.4) 小结
JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。
索引库操作的基本步骤:
- 初始化RestHighLevelClient
- 创建XxxIndexRequest。XXX是Create、Get、Delete
- 准备DSL( Create时需要,其它是无参)
- 发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete
(3) RestClient操作文档
(3.1) 初始化
为了与上述索引库操作分离,我们再次增加一个测试类,做两件事情:
- 初始化RestHighLevelClient
- 我们的酒店数据在数据库,需要利用IHotelService去查询,所以注入这个接口
- 添加@SpringBootTest注解,否则无法注入接口
package cn.itcast.hotel;import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.service.IHotelService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;
import java.util.List;@SpringBootTest
public class HotelDocumentTest {@Autowiredprivate IHotelService hotelService;private RestHighLevelClient client;@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")));}// CRUD操作@AfterEachvoid tearDown() throws IOException {this.client.close();}
}
(3.2) 新增文档
目的:将数据库的酒店数据查询出来,写入elasticsearch中。
(3.2.1) 索引库实体类
数据库查询后的结果是一个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
因此,我们需要定义一个新的类型,与索引库结构吻合:
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();}
}
(3.2.2) 语法说明
对应的java代码如图:
可以看到与创建索引库类似,同样是三步走:
- 创建Request对象
- 准备请求参数,也就是DSL中的JSON文档
- 发送请求
变化的地方在于,这里直接使用client.xxx()的API,不再需要client.indices()了。
(3.2.3) 完整代码
我们导入酒店数据,基本流程一致,但是需要考虑几点变化:
- 酒店数据来自于数据库,我们需要先查询出来,得到hotel对象
- hotel对象需要转为HotelDoc对象
- HotelDoc需要序列化为json格式
创建HotelDocumentTest测试类,编写单元测试,代码整体步骤如下:
@Test
void testAddDocument() throws IOException {// 1.根据id查询酒店数据Hotel hotel = hotelService.getById(61083L);// 2.转换为文档类型,Hotel封装为HotelDocHotelDoc hotelDoc = new HotelDoc(hotel);// 3.将HotelDoc转jsonString json = JSON.toJSONString(hotelDoc);// 1.准备Request对象,指定索引库名和idIndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());// 2.准备Json文档request.source(json, XContentType.JSON);// 3.发送请求client.index(request, RequestOptions.DEFAULT);
}
(3.2.4) 测试
在dev tool中查询我们可以看到已经成功添加了一条文档数据
(3.3) 查询文档
(3.3.1) 语法说明
查询操作非常简单,不过查询的目的是得到封装实体类结果。因此难点是解析为HotelDoc。
可以看到,结果是一个JSON,其中文档放在一个_source
属性中,因此解析就是拿到_source
,反序列化为Java对象即可。
与之前类似,也是三步走:
- 准备Request对象。这次是查询,所以是GetRequest
- 发送请求,得到结果。因为是查询,这里调用client.get()方法
- 解析结果,就是对JSON做反序列化
(3.3.2) 完整代码
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
@Test
void testGetDocumentById() throws IOException {// 1.准备RequestGetRequest request = new GetRequest("hotel", "61082");// 2.发送请求,得到响应GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.解析响应结果String json = response.getSourceAsString();// 4.使用fastJson解析Json字符串HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);
}
(3.3.3) 测试
可以看到结果和我们插入的数据一致
(3.4) 删除文档
与查询类似,删除操作也非常简单:
- 准备Request对象,因为是删除,这次是DeleteRequest对象。要指定索引库名和id
- 发送请求。因为是删除,所以是client.delete()方法
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
@Test
void testDeleteDocument() throws IOException {// 1.准备RequestDeleteRequest request = new DeleteRequest("hotel", "61083");// 2.发送请求client.delete(request, RequestOptions.DEFAULT);
}
(3.5) 修改文档
(3.5.1) 语法说明
修改我们讲过两种方式:
- 全量修改:本质是先根据id删除,再新增
- 增量修改:修改文档中的指定字段值
在RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:
- 如果新增时,ID已经存在,则修改
- 如果新增时,ID不存在,则新增
这里不再赘述,我们主要关注增量修改。
代码示例如图:
与之前类似,也是三步走:
- 准备Request对象。这次是修改,所以是UpdateRequest
- 准备参数。里面包含要修改的字段
- 更新文档。这里调用client.update()方法
(3.5.2) 完整代码
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
@Test
void testUpdateDocument() throws IOException {// 1.准备RequestUpdateRequest request = new UpdateRequest("hotel", "61083");// 2.准备请求参数request.doc("price", "952","starName", "四钻");// 3.发送请求client.update(request, RequestOptions.DEFAULT);
}
(3.6) 批量操作文档
(3.6.1) 语法说明
批量处理BulkRequest,其本质就是将多个普通的CRUD请求组合在一起发送。
其中提供了一个add方法,用来添加其他请求:
可以看到,能添加的请求包括:
- IndexRequest,也就是新增
- UpdateRequest,也就是修改
- DeleteRequest,也就是删除
因此Bulk中添加了多个IndexRequest,就是批量新增功能了。示例:
(3.6.2) 案例
目的:从数据中查询酒店数据,利用BulkRequest批量导入到索引库中
其实还是三步走:
- 创建Request对象。这里是BulkRequest
- 准备参数。批处理的参数,就是其它Request对象,这里就是多个IndexRequest
- 在导入酒店数据时,可以使用for循环批量添加参数。
- 发起请求。这里是批处理,调用的方法为client.bulk()方法
(3.6.3) 完整代码
在hotel-demo的HotelDocumentTest测试类中,编写单元测试:
@Test
void testBulkRequest() throws IOException {// 在数据库批量查询酒店数据List<Hotel> hotels = hotelService.list();// 1.创建RequestBulkRequest request = new BulkRequest();// 2.准备参数,添加多个新增的Requestfor (Hotel hotel : hotels) {// 2.1.转换为文档类型HotelDocHotelDoc 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);
}
(3.7) 小结
文档操作的基本步骤:
- 初始化RestHighLevelClient
- 创建XxxRequest。XXX是Index、Get、Update、Delete、Bulk
- 准备参数(Index、Update、Bulk时需要)
- 发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete、bulk
- 解析结果(Get时需要)
相关文章:

【微服务】Elasticsearch文档索引库操作(二)
🚗Es学习第二站~ 🚩Es学习起始站:【微服务】Elasticsearch概述&环境搭建(一) 🚩本文已收录至专栏:微服务探索之旅 👍希望您能有所收获 一.索引库操作 索引库就类似数据库表,mapping映射就类…...

【论文速递】NAACL2022-DEGREE: 一种基于生成的数据高效事件抽取模型
【论文速递】NAACL2022-DEGREE: 一种基于生成的数据高效事件抽取模型 【论文原文】:DEGREE A Data-Efficient Generation-Based Event Extraction Mode 【作者信息】:I-Hung Hsu , Kuan-Hao Huang, Elizabeth Boschee ÿ…...

C++类和对象(下)
✨个人主页: Yohifo 🎉所属专栏: C修行之路 🎊每篇一句: 图片来源 I do not believe in taking the right decision. I take a decision and make it right. 我不相信什么正确的决定。我都是先做决定,然后把…...

Java常见的六种线程池、线程池-四种拒绝策略总结
点个关注,必回关 一、线程池的四种拒绝策略: CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。 一般并发比较小,性能要求不高,不允许失败。 但是,由于…...

Node=>Express中间件分类 学习4
1.中间件分类 应用级别的中间件路由级别的中间件错误级别的中间件Express 内置的中间件第三方的中间件 通过app.use()或app.get()或app.post()绑定到app实力上的中间件,叫做应用级别的中间件 …...

在阿里当外包,是一种什么工作体验?
上周和在阿里做外包的朋友一起吃饭,朋友吃着吃着,就开启了吐槽模式。 他一边喝酒一边说,自己现在做着这份工作,实在看不到前途。 看他状态不佳,问了才知道,是手上的项目太磨人。 他们现在做的项目&#…...

Vue3快速入门【二】
Vue3快速入门一、传值父传子,子传父v-model二、插槽2.1、匿名插槽2.2、具名插槽2.3、插槽作用域2.4、插槽作用域案例2.4.1、初始布局2.4.2、插槽使用2.4.3、点击编辑按钮获取本行数据(插槽作用域的使用)2.4.4、类型书写优化2.4.5、全局接口抽…...

C++-类和对象(上)
类和对象(上)一,构造函数1,概念2,特性二,析构函数1,概念2,特性三,拷贝构造1,概念2,特性四,运算符重载1,概念2,…...

CAPL(vTESTStudio) - DoIP - TCP接收_04
TCP接收 函数介绍 TcpOpen函数...

联合培养博士经历对于国内就业有优势吗?
2023年国家留学基金委(CSC)申请在即,很多在读博士在关心申报的同时,也对联培经历能否有助于国内就业心中存疑,故此知识人网小编重点解答此问题。之前,我们在“CSC联合培养-国内在读博士出国的绝佳选择”一文…...

测试左移之需求质量
测试左移的由来 缺陷的修复成本逐步升高 下面是质量领域司空见惯的一张图,看图说话,容易得出:大部分缺陷都是早期引入的,同时大部分缺陷都是中晚期发现的,而缺陷发现的越晚,其修复成本就越高。因此&#…...

【数据结构初阶】第三节.顺序表详讲
文章目录 前言 一、顺序表的概念 二、顺序表功能接口概览 三、顺序表基本功能的实现 四、四大功能 1、增加数据 1.1 头插法: 1.2 尾插法 1.3 指定下标插入 2、删除数据 2.1 头删 2.2 尾删 2.3 指定下标删除 2.4 删除首次出现的指定元素 3、查找数据…...

新手小白适合做跨境电商吗?
今天的跨境电商已经逐渐成熟,靠运气赚钱的时代早已过去,馅饼不可能从天上掉下来,尤其是你想做一个没有货源的小白劝你醒醒。做跨境电商真的不容易,要想做,首先要分析自己是否适合做。米贸搜整理了以下资料,…...
Python搭建自己[IP代理池]
IP代理是什么:ip就是访问网页数据服务器位置信息,每一个主机或者网络都有一个自己IP信息为什么要使用代理ip:因为在向互联网发送请求中,网页端会识别客户端是真实用户还是爬虫程序,在今天以互联网为主导的世界中&#…...

pandas——plot()方法可视化
pandas——plot()方法可视化 作者:AOAIYI 创作不易,如果觉得文章不错或能帮助到你学习,记得点赞收藏评论哦 在此,感谢你的阅读 文章目录pandas——plot()方法可视化一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤…...
【Three.js基础】坐标轴辅助器、requestAnimationFrame处理动画、Clock时钟、resize页面尺寸(二)
🐱 个人主页:不叫猫先生 🙋♂️ 作者简介:前端领域新星创作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫系列专栏:vue3从入门…...

C++之完美转发、移动语义(forward、move函数)
完美转发1. 在函数模板中,可以将自己的参数“完美”地转发给其它函数。所谓完美,即不仅能准确地转发参数的值,还能保证被转发参数的左、右值属性不变。2. C11标准引入了右值引用和移动语义,所以,能否实现完美转发&…...

LeetCode刷题系列 -- 48. 旋转图像
给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。示例 1:输入:matrix [[1,2,3],[4,5,6],[7,8,9]]输出&#…...

在多线程环境下使用哈希表
一.HashTable和HashMapHashTable是JDK1.0时创建的,其在创建时考虑到了多线程情况下存在的线程安全问题,但是其解决线程安全问题的思路也相对简单:在其众多实现方法上加上synchronized关键字(效率较低),保证…...

【排序算法】堆排序(Heap Sort)
堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序介绍学习堆排序之前,有必要了解堆!若…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...