当前位置: 首页 > news >正文

Elasticsearch 映射(mapping)

概念

在 Elasticsearch 中,映射(Mapping)定义了索引中字段的类型和属性。它是索引数据结构的基础,类似于传统数据库中的表结构定义。映射不仅定义了字段的类型(如 ​text​、​keyword​、​integer​ 等),还定义了字段的分析器、是否存储、是否索引等属性。映射是 Elasticsearch 中定义索引字段类型和属性的重要概念。通过显式定义映射,你可以控制字段的类型、分析器和其他属性,从而更好地管理和优化索引数据。动态映射则提供了灵活性,使得在没有显式映射的情况下也能插入数据。

映射的基本概念
  1. 字段类型:Elasticsearch 支持多种字段类型,包括文本(​text​)、关键字(​keyword​)、整数(​integer​)、浮点数(​float​)、日期(​date​)、布尔(​boolean​)等。

  2. 分析器:对于文本字段,可以指定分析器(Analyzer),用于在索引和搜索时对文本进行分词和处理。

  3. 多字段:一个字段可以有多个子字段(Multi-fields),每个子字段可以有不同的类型和分析器。

  4. 动态映射:如果没有显式定义映射,Elasticsearch 可以根据插入的数据自动推断字段类型,这称为动态映射(Dynamic Mapping)。

动态映射规则

动态映射(Dynamic Mapping)是 Elasticsearch 中一个非常强大的功能,它允许 Elasticsearch 根据插入的数据自动推断字段类型,从而简化索引的创建和管理。Elasticsearch 使用一组预定义的规则来推断字段类型,这些规则称为动态映射规则。

以下是 Elasticsearch 中一些常见的动态映射规则:

1. 字符串(String)
   - 如果字符串包含日期格式,Elasticsearch 会将其推断为 `date` 类型。
   - 如果字符串包含数字格式,Elasticsearch 会将其推断为 `float` 或 `long` 类型。
   - 否则,Elasticsearch 会将其推断为 `text` 类型,并为其创建一个子字段 `keyword` 类型。

2. 数字(Number)
   - 如果字段值是整数,Elasticsearch 会将其推断为 `long` 类型。
   - 如果字段值是浮点数,Elasticsearch 会将其推断为 `float` 类型。

3. 布尔(Boolean)
   - 如果字段值是 `true` 或 `false`,Elasticsearch 会将其推断为 `boolean` 类型。

4. 对象(Object)
   - 如果字段值是一个 JSON 对象,Elasticsearch 会将其推断为 `object` 类型。

5. 数组(Array)
   - 如果字段值是一个数组,Elasticsearch 会根据数组中的第一个元素类型来推断字段类型。

6. 日期(Date)
   - 如果字段值是一个日期字符串,Elasticsearch 会将其推断为 `date` 类型。

示例

假设你插入以下文档到 Elasticsearch:

PUT /my_index/_doc/1
{"name": "John Doe","age": 30,"is_active": true,"created_at": "2023-10-01T12:00:00Z","tags": ["elasticsearch", "mapping"]
}

Elasticsearch 会根据动态映射规则推断以下字段类型:

  • `name`:`text` 类型,并为其创建一个子字段 `keyword` 类型。
  • `age`:`long` 类型。
  • `is_active`:`boolean` 类型。
  • `created_at`:`date` 类型。
  • `tags`:`keyword` 类型(因为数组中的元素是字符串)。
控制动态映射

你可以通过设置索引的动态映射策略来控制动态映射的行为。以下是一些常见的动态映射策略:

1. **true**:启用动态映射(默认)。
2. **false**:禁用动态映射,忽略新字段。
3. **strict**:如果遇到新字段,抛出异常。

例如,禁用动态映射:

PUT /my_index
{"mappings": {"dynamic": "false"}
}

动态映射规则是 Elasticsearch 自动推断字段类型的一组预定义规则。通过了解这些规则,你可以更好地理解和控制 Elasticsearch 如何处理新字段。动态映射提供了灵活性,使得在没有显式映射的情况下也能插入数据,但有时也需要通过设置动态映射策略来控制其行为。在生产环境中,为了确保数据的结构和类型一致性,以及避免潜在的性能问题和数据不一致,强烈建议显式定义索引的映射。

问题

版本开发中,业务场景需求,增加字段disposalstatus ,升级包中增加了该字段数据模型的SQL语句,由于在升级版本的过程中,升级的时候未先更新数据模型,未先新增字段映射,导致接入数据时,ES采用了动态映射的方式进行了数据的写入,然后再升级数据模型和ES索引mapping更新时,索引中字段已新增,并且字段类型不一致,触发了报错

[2024-08-02T17:37:59,956][DEBUG][o.e.a.a.i.m.p.TransportPutMappingAction] [HOxfa0m] failed to put mappings on indices [[[alert_trace_v0/htU57CoYTQeLgs9Cxo2Mvg]]], type [alert_trace]
java.lang.IllegalArgumentException: mapper [disposalstatus] of different type, current_type [text], merged_type [keyword]at org.elasticsearch.index.mapper.FieldMapper.doMerge(FieldMapper.java:354) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.TextFieldMapper.doMerge(TextFieldMapper.java:876) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.FieldMapper.merge(FieldMapper.java:340) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.FieldMapper.merge(FieldMapper.java:52) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.ObjectMapper.doMerge(ObjectMapper.java:487) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.RootObjectMapper.doMerge(RootObjectMapper.java:278) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.ObjectMapper.merge(ObjectMapper.java:457) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.RootObjectMapper.merge(RootObjectMapper.java:273) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.Mapping.merge(Mapping.java:91) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.index.mapper.DocumentMapper.merge(DocumentMapper.java:339) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.metadata.MetaDataMappingService$PutMappingExecutor.applyRequest(MetaDataMappingService.java:273) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.metadata.MetaDataMappingService$PutMappingExecutor.execute(MetaDataMappingService.java:231) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.service.MasterService.executeTasks(MasterService.java:643) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.service.MasterService.calculateTaskOutputs(MasterService.java:270) ~[elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.service.MasterService.runTasks(MasterService.java:200) [elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.service.MasterService$Batcher.run(MasterService.java:135) [elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.service.TaskBatcher.runIfNotProcessed(TaskBatcher.java:150) [elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.cluster.service.TaskBatcher$BatchedTask.run(TaskBatcher.java:188) [elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:708) [elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:252) [elasticsearch-6.8.23.jar:6.8.23]at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:215) [elasticsearch-6.8.23.jar:6.8.23]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_332]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_332]at java.lang.Thread.run(Thread.java:750) [?:1.8.0_332]
问题一,出现这个错误会影响数据的写入吗

在Elasticsearch中,当你遇到类似 [DEBUG][o.e.a.a.i.m.p.TransportPutMappingAction] ... failed to put mappings ... mapper [disposalstatus] of different type, current_type [text], merged_type [keyword] 的错误时,这意呀着你尝试更改一个已存在字段(在这个例子中是 disposalstatus)的类型,但是Elasticsearch不允许直接更改已索引字段的类型。

关于为什么这个错误“不会影响 disposalstatus 字段的写入”,这主要是因为Elasticsearch在写入数据时不会重新评估或更改字段的映射。一旦数据被索引,它就被存储为与当时字段映射相匹配的形式。因此,即使你尝试更改映射并失败了,已经存在的数据(包括 disposalstatus 字段)仍然保持原样,并且新的写入操作(如果它们遵循现有的映射)仍然可以成功进行。

然而,这并不意味着你可以随意写入与当前映射不匹配的数据类型到 disposalstatus 字段。如果字段的当前类型是 text,并且你尝试写入一个 data 类型(注意:Elasticsearch中没有内置的 data 类型,我猜测你可能是指的复杂数据类型如 objectarray 或其他JSON兼容类型)或 boolean 类型,Elasticsearch将尝试将这些数据转换为与字段映射兼容的形式。

  • 对于 boolean 类型,如果 disposalstatus 字段是 text 类型,并且你尝试写入一个布尔值(如 true 或 false),Elasticsearch将把这些值作为字符串处理,并存储在索引中。虽然查询时可能需要特别注意类型转换,但写入操作本身通常是成功的。

  • 对于复杂数据类型(如 object 或 array),如果 disposalstatus 字段是 text 类型,并且你尝试写入一个对象或数组,Elasticsearch的行为将取决于你的Elasticsearch版本和配置。在某些情况下,它可能会尝试将这些对象或数组转换为字符串(例如,通过JSON序列化),但这通常不是最佳实践,因为这会丢失结构信息并使查询变得复杂。在较新的Elasticsearch版本中,尝试写入不兼容类型的数据可能会导致错误。

总之,错误 mapper [disposalstatus] of different type 不会影响已经存在的 disposalstatus 字段的写入(只要写入的数据类型与当前映射兼容),但它会阻止你更改字段的类型。如果你需要存储不同类型的数据,你应该考虑创建一个新字段,并在写入新数据时同时更新这两个字段。此外,对于复杂数据类型和布尔值,你应该确保字段的映射与你要存储的数据类型相匹配。

问题二:数据可以正常写入,但是能正常的查询,排序,聚合等操作吗
Fielddata is disabled on text fields by default. Set fielddata=true on [disposalstatus] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.

在Elasticsearch中,fielddata 默认在 text 类型的字段上是禁用的。fielddata 是一种将数据从磁盘上的倒排索引(inverted index)加载到内存中以便进行排序、聚合、脚本执行等操作的功能。但是,由于 text 字段通常包含大量文本,如果启用 fielddata,可能会消耗大量内存,影响Elasticsearch集群的性能和稳定性。

错误信息中提到“Fielddata is disabled on text fields by default. Set fielddata=true on [disposalstatus] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead.” 是在告诉你几个关键点:

  1. 默认禁用text 字段上的 fielddata 默认是禁用的。
  2. 启用fielddata:如果你确实需要在 disposalstatus 字段上使用 fielddata(比如进行排序或聚合操作),你可以在字段映射中设置 fielddata=true。但是,这可能会消耗大量内存。
  3. 使用keyword字段:作为替代方案,你可以将 disposalstatus 字段的类型更改为 keywordkeyword 类型的字段天然支持 fielddata,因为它们通常用于存储不需要全文搜索的精确值(如标签、枚举值等)。
为什么使用 keyword 字段?
  • 内存使用keyword 字段的 fielddata 消耗的内存通常比 text 字段少,因为 keyword 字段不包含分词(tokenization)和索引(indexing)过程中产生的额外信息。
  • 性能:对于排序、聚合和脚本等需要 fielddata 的操作,keyword 字段通常能提供更好的性能。
  • 用途keyword 字段非常适合存储不需要全文搜索的精确字符串值。
如何更改字段类型?

如果你需要更改 disposalstatus 字段的类型从 text 到 keyword,并且该字段尚未包含大量数据,你可以通过以下步骤进行:

  1. 更新映射:使用Elasticsearch的映射API来更新索引的映射,将 disposalstatus 字段的类型更改为 keyword。但是,请注意,直接更改已存在字段的类型通常是不允许的。因此,你可能需要:

    • 删除索引并重新创建它,包含新的映射。
    • 或者,如果可能的话,使用别名(alias)和索引滚动更新(rolling updates)来最小化停机时间。
    • 在某些情况下,如果Elasticsearch版本和配置允许,你可以使用索引模板来为新文档设置新的字段类型,但已存在的文档不会受到影响。
  2. 重新索引数据(如果需要):如果你选择了删除并重新创建索引的方法,你需要将旧索引中的数据重新索引到新索引中。

  3. 验证更改:在更改生效后,验证新索引和映射是否符合预期,并确保应用程序可以正确地与新的索引和映射交互。

请注意,在进行此类更改之前,最好先在测试环境中验证更改的影响。

建议

  1. 在生产环境中,为了确保数据的结构和类型一致性,以及避免潜在的性能问题和数据不一致,强烈建议显式定义索引的映射,设置索引的动态映射策略为禁用动态映射,忽略新字段。
  2. 针对出现的字段映射不一致的问题,采用重建索引(reindex)的方式进行修正,避免出现存储查询排序聚合等错误。

相关文章:

Elasticsearch 映射(mapping)

概念 在 Elasticsearch 中,映射(Mapping)定义了索引中字段的类型和属性。它是索引数据结构的基础,类似于传统数据库中的表结构定义。映射不仅定义了字段的类型(如 ​text​、​keyword​、​integer​ 等)…...

开放式耳机更适合运动的时候使用?开放式耳机推荐指南

开放式耳机确实非常适合运动时使用,原因主要有以下几点。 首先,保持对外界的感知是很重要的一点。在运动的时候,我们需要听到周围的环境声音,比如车辆的行驶声、行人的呼喊等,以便及时做出反应,保证自身安全…...

食堂窗口自助点餐小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,商家管理,店铺信息管理,菜品分类管理,菜品信息管理,订单管理,系统管理 微信端账号功能包括:系统首页&#…...

请说出路由传参和获取参数的三种方式

在Vue.js中使用Vue Router进行路由管理时,传递和获取参数是常见的需求。这里介绍三种主要的路由传参和获取参数的方式: 1. 通过URL的查询参数(Query Parameters) 传递参数: 当你需要传递一些非敏感数据(…...

精准防控,高效管理:AI智能分析网关V4区域未停留检测算法的介绍及应用

一、区域未停留AI检测算法概述 随着人工智能和计算机视觉技术的飞速发展,区域未停留AI检测算法作为一种重要的视频分析技术,逐渐在各个领域得到广泛应用。该算法通过高效处理视频流数据,能够实时分析并判断目标对象是否在预设区域内有足够的…...

html+css練習:iconfont使用

1.網址地址:https://www.iconfont.cn/search/index 2.註冊登錄,將需要的圖標添加到購物車 3.下載代碼 4.下載后的代碼有一個html頁面,裡面有詳細的使用方式...

算法导论 总结索引 | 第五部分 第二十一章:用于不相交集合的数据结构

一些应用涉及 将n个不同的元素分成一组不相交的集合。寻找包含给定元素的唯一集合 和 合并两个集合 1、不相交集合的操作 1、一个不相交集合 数据结构 维持了 一个不相交动态集的集合 S {S_1, S_2,…, S_n}。用一个代表 来标识每个集合,它是这个集合的某个成员。…...

【单例设计模式】揭秘单例模式:从原理到实战的全方位解析(开发者必读)

文章目录 深入理解单例设计模式:原理、实现与最佳实践引言第一部分:设计模式简介第二部分:单例模式定义第三部分:单例模式的优点和缺点第四部分:单例模式的实现方式懒汉式非线程安全的实现线程安全的实现(双…...

VTK8.2.0编译(Qt 5.14.2+VS2017)

VTK8.2.0编译(Qt 5.14.2VS2017) 关于Qt和MSVC的安装,可以参考文章(QtMSVC2017)。 本篇VTK在QtMSVC的配置下的编译。VTK 以8.2.0为例。 一、环境变量的配置 我们打开电脑的环境变量,可以看到没有Qt相关的…...

武汉流星汇聚:亚马逊跨境电商龙头,市场份额稳固,服务品质卓越

在全球跨境电商的版图上,亚马逊无疑是一颗璀璨的明星,以其庞大的市场规模、卓越的用户体验和强大的品牌影响力,稳居行业龙头地位。即便在诸多新兴跨境平台竞相崛起的背景下,亚马逊依然以其独特的优势,保持着难以撼动的…...

我出一道面试题,看看你能拿 3k 还是 30k!

大家好,我是程序员鱼皮。欢迎屏幕前的各位来到今天的模拟面试现场,接下来我会出一道经典的后端面试题,你只需要进行 4 个简单的选择,就能判断出来你的水平是新手(3k)、初级(10k)、中…...

opecv c++计算图像的曲率

公式 κ z x x ⋅ z y 2 − 2 ⋅ z x ⋅ z y ⋅ z x y z y y ⋅ z x 2 ( z x 2 z y 2 1 ) 3 / 2 \kappa \frac{z_{xx} \cdot z_y^2 - 2 \cdot z_x \cdot z_y \cdot z_{xy} z_{yy} \cdot z_x^2}{(z_x^2 z_y^2 1)^{3/2}}\newline κ(zx2​zy2​1)3/2zxx​⋅zy2​−2⋅zx​…...

鸿蒙 IM 即时通讯开发实践,融云 IM HarmonyOS NEXT 版

融云完成针对“纯血鸿蒙”操作系统的 SDK 研发,HarmonyOS NEXT 版融云 IM SDK 已上线,开发者可在“鸿蒙生态伙伴 SDK 市场”查询使用。 发挥 20 年通信行业技术积累和领创品牌效应,融云为社交、娱乐、游戏、电商、出行、医疗等各行业提供专业…...

【全国大学生电子设计竞赛】2022年D题

🥰🥰全国大学生电子设计大赛学习资料专栏已开启,限时免费,速速收藏~...

【优秀python案例】基于python爬虫的深圳房价数据分析与可视化实现

现如今,房价问题一直处于风口浪尖,房价的上涨抑或下跌都牵动着整个社会的利益,即便是政府出台各种政策方针也只能是暂时抑制楼市的涨势,对于需要买房的人来说,除了关注这些变化和政策外,还有一个非常头疼的…...

vscode安装与配置本地c/c++编译调试环境

目录 (1)安装vscode和常用插件 1.下载安装vscode 2.安装常用插件 (2)本地安装和配置编译器 1.安装编译器 2.vscode配置编译器 第1种:全局配置 第2种:为当前项目个性化配置 (3&#xff…...

PCIe学习笔记(15)

设备就绪状态 (Device Readiness Status,DRS)消息 (Device Readiness Status (DRS) 是PCIe规范中引入的一种机制,旨在改进设备初始化和就绪状态的检测与报告。 在以往的PCIe版本中,系统通常依赖于固定的超时机制来判断设备是否已…...

Rust中的特殊类型所占的内存大小

可以使用std::mem:size_of获取类型大小&#xff1a; use std::mem::size_of;struct Journal(String, u32); trait Summary {} impl Summary for Journal {}fn main() {println!("普通结构体相关&#xff1a;");println!("{}", size_of::<&Journal&…...

【深度学习】变分自编码器 VAE,什么是变分?(1)

文章目录 1. 变分自编码器 VAEVAE的基本概念VAE的数学原理编码器解码器目标函数训练过程代码示例未来发展2. 变分推断变分推断(Variational Inference)变分推断的基本概念变分推断的目标变分下界(Evidence Lower Bound, ELBO)最大化变分下界变分推断的步骤3. 必读内容1. 变…...

宏编程:C++宏、Rust宏和Lisp宏比较

根据simondobson两篇文章&#xff08;1、2&#xff09;&#xff0c;总结比较一下C宏 Rust宏和Lisp宏&#xff1a; Rust 宏&#xff1a;Rust 有两种类型的宏&#xff1a; 声明性宏&#xff1a;这些模式匹配参数来生成代码。 过程宏&#xff1a;这些宏执行从代码到代码的更一般…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别

OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...