Java 操作ElasticSearch

news2024/10/6 19:30:45

        Java REST提供了两种风格的客户端连接工具,Java High Level REST Client、Java Low Level REST Client,这里我就不去细说Java Low Level REST Client了,因为这我确实没用到过,也不是很了解,我说一下Java High Level REST Client。

Java High Level REST Client ​​​​      

        首先如果你喜欢看官方文档的话,我把地址粘贴在这里,官网讲的也比较详细:Java High Level REST Client | Java REST Client [7.4] | Elastic

第一步添加依赖:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.4.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-client -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>7.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.4.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.69</version>
        </dependency>

第二步:

在配置文件添加对应的地址以及端口:

elasticsearch:
  host: 127.0.0.1
  port: 9200

 第三步使用:

1.创建一个索引

	@Autowired
	private RestHighLevelClient client;  //注入client、后面的代码会省略
	
  @Test
	public void addIndexAndmapping() throws IOException {
		IndicesClient indices = client.indices();
		//创建索引
		CreateIndexRequest createIndexRequest = new CreateIndexRequest("test_index");
		//设置分片数量以及副本数量
		createIndexRequest.settings(Settings.builder()
				.put("index.number_of_shards", 3)
				.put("index.number_of_replicas", 2)
		);
		//添加映射,相当于给表创建字段
		String mapping  ="{properties={address={analyzer=ik_max_word, type=text}, name={type=keyword}, age={type=integer}}}";
		System.out.println(mapping);
		createIndexRequest.mapping(mapping, XContentType.JSON);
		CreateIndexResponse response = indices.create(createIndexRequest, RequestOptions.DEFAULT);//创建索引
		System.out.println(response.isAcknowledged());
	}

2.查询某个索引的信息

	@Test
	public void queryIndex() throws IOException {
		IndicesClient indices = client.indices();
		GetIndexRequest getIndexRequest = new GetIndexRequest("person");
		GetIndexResponse getIndexResponse = indices.get(getIndexRequest, RequestOptions.DEFAULT);
		Map<String, MappingMetaData> mappings = getIndexResponse.getMappings();
		mappings.forEach((k,v)->{
			System.out.println("key:"+k+",v:"+v.getSourceAsMap());
		});
	}

3.添加文档

	@Test
	public void addDoc() throws IOException {
		//数据对象
		Person p = new Person();
		p.setName("meiting");
		p.setAddress("sichuan");
		p.setAge(22);
		IndexRequest request = new IndexRequest("person").id("1").source(JSON.toJSONString(p),XContentType.JSON);
		IndexResponse index = client.index(request, RequestOptions.DEFAULT);
	}

4.修改文档

就跟添加文档一样,在es中如果指定文档的id存在就会就会更新这个文档。操作方式跟上面添加文档一样,不过需要指定文档的id。

5.查询操作

5.1根据id查询文档或者删除文档

 @Test
	public void findDocByID() throws IOException {
		GetRequest getIndexRequest = new GetRequest("person","1");
		GetResponse documentFields = client.get(getIndexRequest, RequestOptions.DEFAULT);
		System.out.println(documentFields.getSourceAsString());
	}
  //根据id删除文档
	@Test
	public void delDocByID() throws IOException {
		DeleteRequest deleteRequest = new DeleteRequest("person","1");
		DeleteResponse documentFields = client.delete(deleteRequest, RequestOptions.DEFAULT);
		System.out.println(documentFields.getId());
	}

5.2查询所有文档

	@Test
	public void findAllDoc() throws IOException {
		SearchRequest sr = new SearchRequest("person");

		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		sourceBuilder.from(0).size(20);//指定分页
		MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
		sourceBuilder.query(queryBuilder);
		sr.source(sourceBuilder);
		SearchResponse search = client.search(sr, RequestOptions.DEFAULT);
		System.out.println(search.getHits().getTotalHits()); //查询到的所有的文档数量
		SearchHits hits = search.getHits();
		hits.forEach(ele->{
			System.out.println(ele.getSourceAsString());
		});
	}

5.3term查询(词条查询) text支持分词,keyword不支持分词

    @Test
	public void termQuery() throws IOException {
		SearchRequest requst = new SearchRequest("person");
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

		QueryBuilder queryBuilder = QueryBuilders.termQuery("name","阿");
		sourceBuilder.query(queryBuilder);

		requst.source(sourceBuilder);
		SearchResponse search = client.search(requst, RequestOptions.DEFAULT);

		SearchHit[] hits = search.getHits().getHits();
		for (SearchHit hit : hits) {
			System.out.println(hit.getSourceAsString());
		}
	}
/** 类似于
get person/_search
{
  "query":{
    "term":{
      "name":{
        "value":"阿"
      }
    }
  }
}
*/

5.4match查询

	@Test
	public void matchQuery() throws IOException {
		SearchRequest requst = new SearchRequest("person");
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "老板");
		queryBuilder.operator(Operator.AND);//求并集
		sourceBuilder.query(queryBuilder);
		requst.source(sourceBuilder);
		SearchResponse search = client.search(requst, RequestOptions.DEFAULT);
		SearchHit[] hits = search.getHits().getHits();
		for (SearchHit hit : hits) {
			System.out.println(hit.getSourceAsString());
		}
	}
/**类似于
get person/_search
{
  "query":{
    "match": {
      "name": {
        "query":"永恩",
        "operator": "and"
      }
    }
  }
}
*/

5.5模糊查询

wildcard查询:会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) *(0个或者多个字符)

regexp查询:正则查询

prefix查询:前缀查询

	@Test
	public void wildSearch() throws IOException {
		SearchRequest requst = new SearchRequest("person");
		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

		QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("name","菲*");
		//QueryBuilder queryBuilder = QueryBuilders.regexpQuery("name","菲*");  //正则查询
		//QueryBuilder queryBuilder = QueryBuilders.prefixQuery("name","菲"); //前缀查询
		sourceBuilder.query(queryBuilder);
		requst.source(sourceBuilder);
		SearchResponse search = client.search(requst, RequestOptions.DEFAULT);
		SearchHit[] hits = search.getHits().getHits();
		for (SearchHit hit : hits) {
			System.out.println(hit.getSourceAsString());
		}
	}

5.6范围查询

range范围查询:查找指定字段在指定范围内包含值。查询年龄20到26的人并排序

	@Test
	public void rangeQuery() throws IOException {
		SearchRequest requst = new SearchRequest("person");

		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
		QueryBuilder queryBuilder = QueryBuilders.rangeQuery("age").gte(20).lte(26);
		sourceBuilder.query(queryBuilder);
		sourceBuilder.sort("age", SortOrder.DESC); //排序
		requst.source(sourceBuilder);
		SearchResponse search = client.search(requst, RequestOptions.DEFAULT);
		SearchHit[] hits = search.getHits().getHits();
		for (SearchHit hit : hits) {
			System.out.println(hit.getSourceAsString());
		}
	}
/**类似于
get person/_search
{
  "query":{
    "range": {
      "age": {
        "gte": 20,
        "lte": 24
      }
    }
  },
  "sort":[  //排序
    {
      "age":{
        "order":"desc"
      }
    }
    ]
}
*/

5.7querySt ring查询

queryString查询就是:对查询条件进行分词,然后将分词后的查询条件和词条进行等值匹配。然后取并集。

这种查询的特点就是可以指定多个字段查询。比如下面就是查名字和地址中包含“老”的数据。

	@Test
	public void queryStringQuery() throws IOException {
		SearchRequest requst = new SearchRequest("person");

		SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

		QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("老").field("name").field("address").defaultOperator(Operator.OR);
		sourceBuilder.query(queryBuilder);
		sourceBuilder.sort("age", SortOrder.DESC); //排序
		requst.source(sourceBuilder);
		SearchResponse search = client.search(requst, RequestOptions.DEFAULT);
		SearchHit[] hits = search.getHits().getHits();
		for (SearchHit hit : hits) {
			System.out.println(hit.getSourceAsString());
		}
	}
/**类似于
get person/_search
{
  "query":{
    "query_string": {
      "fields": ["name","address"],
      "query": "永恩 OR 瑟提"
    }
  }
}
*/

        除了上面说的这些常用的查询操作外还包括许多其他的查询,比如说聚合查询、高亮查询等等。在官网都可以查到对应的例子。到时候可以去官网看对应的例子。

Spring Data 操作ES 

Spring Data也提供了操作ES数据库的功能,因为我们现在的项目基本都是基于Spring的,所以集成这个功能之后很多项目在考虑选择的时候也会把这种方式考了进来,我之前参与的项目就是采用的这种方式来操作ES数据库的。

1.搭建环境

添加依赖:添加依赖的时候要注意版本的选择,要选择对应的版本,参考官网Spring Data Elasticsearch - Reference Documentation

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.11</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springDataEs</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springDataEs</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

然后第二步配置文件

spring.elasticsearch.rest.uris=127.0.0.1:9200 

前面要做的步骤就这两步。

2.实际操作

2.1创建实体以及接口 

@Document(indexName = "animal",createIndex = true,shards = 1,replicas = 1)
@Data
public class Animal {
    @Id
    private long id;

    @Field(type= FieldType.Text)
    private String name;

    @Field(type=FieldType.Text)
    private String address;

    @Field(type = FieldType.Integer)
    private int age;
}

这上面需要注意的就是几个注解:

  • @Document 注解作用在类上,说明这是一个文档对象。

        indexName:索引名称

        createIndex:是否需要创建索引,若为true就会自动创建索引

        shards、replicas:分片数量和副本数量

  • @Field(type= FieldType.Text)

    在es对应的这个字段的数据类型,这里FieldType.Tex在es创建后这个字段就对应为text类型的。

2.2创建存储库接口

创建了这个接口并继承ElasticsearchRepository之后,就可以使用了。

public interface AnimalRepostory extends ElasticsearchRepository<Animal,Long> {
}

继承关系:

然后就可以基本的使用了,步骤非常简单。。。

2.3新增文档 

我新写了一个接口,去尝试添加一个文档。

    @PostMapping("addDoc")
    public void addDoc(){
        Animal animal = new Animal();
        animal.setId(1);
        animal.setName("tew");
        animal.setAddress("111");
        animal.setAge(12);
        animalRepostory.save(animal);
    }

效果

可以看到,我们添加文档成功了,这个索引也自动给我们创建了。

Spring Data ElasticSearch对ES的操作进行了很完美的包装,他是基于Java High Level REST Client写的,使用起来非常方便。这里我就不对其他的方法进行讲解了,它的crud自己去搭建个环境跑起来,只要环境搭好之后后面就很方便了。对于简单的查询我们可以直接创建对应的接口方法就可以了。下面给出官网给出的例子:

interface PersonRepository extends Repository<Person, Long> {

  List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

  // Enables the distinct flag for the query
  List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
  List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);

  // Enabling ignoring case for an individual property
  List<Person> findByLastnameIgnoreCase(String lastname);
  // Enabling ignoring case for all suitable properties
  List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

  // Enabling static ORDER BY for a query
  List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
  List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

分页查询和排序,只需要在定义接口方法的时候给出Pageable以及Sort规则就可以了。

例子:

	@PostMapping("findPage")
    public void findPage(){
        Pageable page =  Pageable.ofSize(3).withPage(1);
        Iterable<Animal> all = animalRepostory.findAll(page);
        for(Iterator<Animal> iterator = all.iterator(); iterator.hasNext();System.out.println(iterator.next())){
        }
    }

    @PostMapping("findPageSort")
    public void findPageSort(){
        Sort sort = Sort.by("age").descending();
        Iterable<Animal> all = animalRepostory.findAll(sort);
        for(Iterator<Animal> iterator = all.iterator(); iterator.hasNext();System.out.println(iterator.next())){
        }
    }

自定义DSL查询:

这里用一个模糊查询举例:

在对应的接口创建一个接口,并在@Query注解里面写上对应的查询语句

public interface AnimalRepostory extends ElasticsearchRepository<Animal,Long> {
    @Query("{\n" +
            "    \"wildcard\": {\n" +
            "      \"name\": {\n" +
            "        \"value\": \"t*\"\n" +
            "      }\n" +
            "    }\n" +
            "  }")
    List<Animal> findTest();
}

效果:

    @PostMapping("findQuery")
    public void findQuery(){
        List<Animal> test = animalRepostory.findTest();
        test.forEach(ele->{
            System.out.println(ele);
        });
    }

Spring Data还提供了很多其他的查询功能,如果有需要用到的我建议可以去看看官网。 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LVS 负载均衡群集的 NAT 模式和 DR 模式

文章目录 一、NAT 模式和 DR 模式的介绍DR模式NAT模式两种模式的区别 二、DR模式集群构建配置 一、NAT 模式和 DR 模式的介绍 DR模式 当用户向负载均衡调度器&#xff08;Director Server&#xff09;发起请求&#xff0c;调度器将请求发往至内核空间PREROUTING链首先会接收到…

【JavaEE】HTML基础知识

目录 1.HTML结构 2.HTML常见标签 3.表格标签 4.列表标签 5.表单标签 ​6.select 标签 7.textarea 标签 8.无语义标签: div & span 9.标签小练习 1.HTML结构 形如&#xff1a; <body idmyId>hello</body> HTML的书写格式 标签名 (body) 放到 <…

【操作系统OS】学习笔记:第二章 进程与线程 (上)【哈工大李治军老师】

基于本人观看学习 哈工大李治军老师主讲的操作系统课程 所做的笔记&#xff0c;仅进行交流分享 特此鸣谢李治军老师&#xff0c;操作系统的神作&#xff01; 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0c;…

58.网页设计规则#5_阴影

一些概念 ● 在一个100%平面设计的时代之后&#xff0c;我们现在又回到了在UI设计中使用阴影(“平面设计2.0”) ● 阴影箱深度(3D):阴影越多&#xff0c;离元素界面越远 利用好阴影 你不必使用阴影!只在对网站个性有意义的情况下使用它们 使用少量的阴影:不要给每个元素…

Jmeter接口自动化测试系列之Http接口自动化实战

以下主要介绍Jmeter接口自动化需要哪些控件、接口自动化实战及总结。 前面的系列文章&#xff0c;介绍了常用组件、参数化、接口依赖、断言等知识点&#xff0c;今天我们要将这些结合起来&#xff0c;进行综合实战。 2023年B站最新Jmeter接口测试实战教程&#xff0c;精通接口…

从一到无穷大 #5 公有云时序数据库定价

文章目录 引言serverless实例售卖结论 Azure CosmosDB预配吞吐量自动缩放吞吐量Serverless预留容量存储量 Amazon Timestream写入计费查询计费存储 阿里云TSDB阿里云Lindom时序引擎实例固定费用存储费用节点费用 华为云GaussDB(for Influx)腾讯云CTSDBTDengineInfluxDB CloudAW…

c++11下篇 + 智能指针

c11下篇 智能指针 1 可变参数模板1.1 递归函数方式展开参数包1.2 逗号表达式展开参数包1.3 STL容器中的empalce相关接口函数&#xff1a; 2 lambda达式2.1 c的痛2.2 lambda表达式语法2.3 函数对象与lambda表达式 3 包装器3.1 bind 4 线程库4.1 thread类的简单介绍4.2 面试题&a…

MySQL示例数据库(MySQL Sample Databases) 之 world_x数据库

文章目录 MySQL示例数据库(MySQL Sample Databases) 之 world_x数据库官方示例数据介绍world_x数据库world_x数据库安装world-db/world.sql的脚本内容参考 MySQL示例数据库(MySQL Sample Databases) 之 world_x数据库 官方示例数据介绍 MySQL 官方提供了多个示例数据库&#…

差分数组 技巧小记

差分数组 差分数组二维差分 差分数组 如果两个信息“长得很像”&#xff0c;只要保留一个&#xff0c;对另一个&#xff0c;只要保留它们的差异&#xff0c;然后进行微调就行了。 差分数组&#xff1a; 3210&#xff0c;3208&#xff0c;3206&#xff0c;3211&#xff0c;32…

Three.js--》Gui.js库的使用讲解

目录 Gui.js库基本使用 使用three自带gui库实现基本操作 gui库实现下拉菜单和单选框 gui库分组方法实现 使用dat.gui第三方库 Gui.js库基本使用 gui.js说白了就是一个前端js库&#xff0c;对HTML、CSS和JavaScript进行了封装&#xff0c;学习开发3d技术时借助该库可以快速…

230502-LLM-Vicuna介绍、安装与注意事项整理

最终效果 在对话过程中&#xff0c;GPU与CPU均会有波动&#xff0c;但是主要还是CPU波动为主 相关资料 序号链接说明001本地CPU6G内存部署类ChatGPT模型&#xff08;Vicuna 小羊驼&#xff09; - 知乎极简安装版本&#xff0c;只支持CPU与命令行002最新开源语言模型 Vicuna 媲…

【Linux进阶之路】初始Linux

文章目录 一.时代背景二.硅谷发展模式三.操作系统基本定义常见的操作系统Linux系统的常见安装方式 四.基本指令的使用登录指令与用户相关的指令ls 指令——信息查看pwd指令——打印当前所处的文件位置cd指令——访问文件rm——删除指令touch——创建文件与修改文件信息tree ——…

Rust - 变量与数据的交互方式(clone)

在上一篇文章中我们介绍了变量与数据的交互方式-move&#xff0c;通过底层原理我们知道Rust 永远也不会自动创建数据的 “深拷贝”。因此&#xff0c;任何 自动的复制可以被认为对运行时性能影响较小。 但是如果我们 确实需要深度复制 String中堆上的数据&#xff0c;而不仅仅…

RT1010 PWM 组成配置和 PWMX 的使用

1. 前言 本篇博文将着眼于 i.MX RT1010 内部的 eFlexPWM&#xff0c;介绍其各个功能模块&#xff0c;以及 PWM 产生的原理。 2. 功能模块组成 以下是 RT1010 内部 PWM 的一个 Submoudle 的组成框图&#xff0c;从框图中我们可以看到&#xff1a; 自左向右依次有 Prescaler 对…

【C++入门】C++为什么要有缺省参数

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

后端程序员的前端必备【Vue】- 01 Vue入门

Vue概述与基础入门 1 Vue简介1.1 简介1.2 MVVM 模式的实现者——双向数据绑定模式1.3 其它 MVVM 实现者1.4 为什么要使用 Vue.js1.5 Vue.js 的两大核心要素1.5.1 数据驱动![请添加图片描述](https://img-blog.csdnimg.cn/963aca7d7a4447009a23f6900fdd7ee1.png)1.5.2 组件化 2 …

IDEA2022版教程上(下载、卸载、安装、新建工程、jdk设置、详细设置、新建/导入/删除 普通java模块、修改普通java模块名、同时打开多个工程、常用代码模板:非空判断,遍历,输出语句快捷键)

0、前景摘要 0.1 概览 0.2 套课程适用人群 初学Java语言&#xff0c;熟悉了记事本、EditPlus、NotePad或Sublime Text3等简易开发工具的Java初学者熟练使用其他Java集成开发环境&#xff08;IDE&#xff09;&#xff0c;需要转向IDEA工具的Java工程师们关注IDEA各方面特性的J…

BPMN2.0 任务-脚本任务

描述 脚本任务(script task)是自动执行的活动。当流程执行到达脚本任务时,会执行相应的脚本。 脚本任务用左上角有一个小“脚本”图标的标准BPMN 2.0任务(圆角矩形)表示。 脚本任务使用script与scriptFormat元素定义。 <scriptTask id="theScriptTask" nam…

Qt中的绘图事件

文章目录 QPainter 绘图绘图设备QPixmap QPainter 绘图 绘图事件 void paintEvent()声明一个画家对象 QPainter painter(this) this指定绘图设备画线、画圆、画矩形、画文字设置画笔 QPen 设置画笔宽度 、风格设置画刷 QBrush 设置画刷 风格 测试 #include "widget.h&quo…

科学计算库Numpy快速入门

目录 Numpy概述array数组数组结构数组类型数值运算排序操作数组形状操作数组生成函数四则运算随机模块文件读写 Numpy概述 NumPy 是 Python 中的一个开源数学库&#xff0c;提供了快速且便捷的数组处理功能&#xff0c;可以用来进行科学计算、数据分析、算法开发等多种任务。N…