原文:
docs.oracle.com/javase/tutorial/reallybigindex.html
20.9.2 组复制状态变量
原文:
dev.mysql.com/doc/refman/8.0/en/group-replication-status-variables.html
MySQL 8.0 支持一个提供有关组复制信息的状态变量。该变量在此处描述:
-
group_replication_primary_member
在单主模式下运行时显示主成员的 UUID。如果组在多主模式下运行,则显示空字符串。 警告group_replication_primary_member
状态变量已被弃用,并计划在将来的版本中删除。 查看第 20.1.3.1.2 节,“查找主”。
20.10 常见问题
原文:
dev.mysql.com/doc/refman/8.0/en/group-replication-frequently-asked-questions.html
本节提供了常见问题的答案。
一个组中 MySQL 服务器的最大数量是多少?
一个组最多可以由 9 台服务器组成。尝试向具有 9 个成员的组添加另一台服务器会导致加入请求被拒绝。这个限制是通过测试和基准测试确定的,是一个安全边界,在稳定的本地区域网络上组表现可靠。
组中的服务器是如何连接的?
组中的服务器通过打开对等 TCP 连接连接到组中的其他服务器。这些连接仅用于组内通信和服务器之间的消息传递。此地址由group_replication_local_address
变量配置。
group_replication_bootstrap_group
选项用于什么目的?
引导标志指示成员创建一个组并充当初始种子服务器。加入组的第二个成员需要请求引导组的成员动态更改配置,以便将其添加到组中。
成员需要在两种情况下引导组。当组最初创建时,或者当关闭并重新启动整个组时。
如何为分布式恢复过程设置凭据?
您可以将用户凭据永久设置为group_replication_recovery
通道的凭据,使用CHANGE REPLICATION SOURCE TO
语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO
语句(MySQL 8.0.23 之前)。另外,从 MySQL 8.0.21 开始,您可以在每次启动 Group Replication 时在START GROUP_REPLICATION
语句中指定它们。
使用CHANGE REPLICATION SOURCE TO
| CHANGE MASTER TO
设置的用户凭据以明文形式存储在服务器上的复制元数据存储库中,但在START GROUP_REPLICATION
中指定的用户凭据仅保存在内存中,并且通过STOP GROUP_REPLICATION
语句或服务器关闭时会被删除。因此,使用START GROUP_REPLICATION
指定用户凭据有助于保护组复制服务器免受未经授权的访问。但是,此方法与通过group_replication_start_on_boot
系统变量指定自动启动组复制不兼容。有关更多信息,请参见 Section 20.6.3.1, “Secure User Credentials for Distributed Recovery”。
我可以使用组复制来扩展我的写入负载吗?
不直接,但 MySQL 组复制是一种共享无内容完全复制解决方案,组中的所有服务器都复制相同数量的数据。因此,如果组中的一个成员将 N 字节写入存储作为事务提交操作的结果,那么其他成员上也大致会写入 N 字节到存储,因为事务在所有地方都被复制。
然而,由于其他成员不必像原始成员在最初执行事务时那样进行相同数量的处理,他们会更快地应用更改。事务以仅用于应用行转换的格式进行复制,而无需重新执行事务(基于行的格式)。
此外,由于更改以基于行的格式传播和应用,这意味着它们以优化和紧凑的格式接收,并且与原始成员相比,可能减少所需的 IO 操作次数。
总结一下,您可以通过将无冲突的事务分布到组中的不同成员来扩展处理能力。您可以很可能扩展出小部分 IO 操作,因为远程服务器只接收读取-修改-写入到稳定存储的必要更改。
与简单复制相比,组复制是否需要更多的网络带宽和 CPU,在相同的工作负载下?
由于服务器需要不断相互交互以进行同步,因此预计会有一些额外负载。很难量化需要多少数据。这也取决于组的大小(三台服务器对带宽需求的压力比九台服务器少)。
内存和 CPU 占用也更大,因为服务器同步部分和组消息传递需要执行更复杂的工作。
我可以在广域网上部署组复制吗?
是的,但是每个成员之间的网络连接 必须 是可靠的,并且具有适当的性能。低延迟、高带宽的网络连接是实现最佳性能的要求。
如果仅网络带宽是问题,那么可以使用 第 20.7.4 节,“消息压缩” 来降低所需的带宽。然而,如果网络丢包导致重传和更高的端到端延迟,吞吐量和延迟都会受到负面影响。
警告
当任何组成员之间的网络往返时间(RTT)为 5 秒或更长时,您可能会遇到问题,因为内置的故障检测机制可能会错误地触发。
在临时连接问题的情况下,成员是否会自动重新加入组?
这取决于连接问题的原因。如果连接问题是暂时的,并且重新连接足够快以至于故障检测器没有意识到它,那么服务器可能不会从组中移除。如果是一个“长期”的连接问题,那么故障检测器最终会怀疑存在问题,并将服务器从组中移除。
从 MySQL 8.0 开始,有两个设置可用于增加成员保持在组中或重新加入组的机会:
-
group_replication_member_expel_timeout
增加了在创建怀疑(在初始 5 秒检测期之后发生)和将成员驱逐之间的时间。您可以设置最多 1 小时的等待时间。从 MySQL 8.0.21 开始,默认设置为 5 秒的等待时间。 -
group_replication_autorejoin_tries
使成员在被驱逐或不可达的大多数超时后尝试重新加入组。成员将按照指定的次数间隔五分钟进行自动重新加入尝试。从 MySQL 8.0.21 开始,默认情况下激活此功能,并且成员进行三次自动重新加入尝试。
如果服务器被从组中驱逐,并且任何自动重新加入尝试都不成功,您需要手动重新加入它。换句话说,当服务器被明确从组中移除后,您需要手动重新加入它(或者有一个脚本自动执行)。
什么时候会将成员从组中排除?
如果成员变得沉默,其他成员将其从组配置中移除。实际上,当成员崩溃或存在网络断开时可能会发生这种情况。
在给定成员经过一定超时后检测到故障,并创建一个不包含静默成员的新配置。
当一个节点明显滞后时会发生什么?
没有一种方法可以自动定义何时从组中自动驱逐成员的策略。您需要找出为什么成员滞后并解决问题,或将该成员从组中移除。否则,如果服务器太慢以至于触发流量控制,那么整个组也会减速。流量控制可以根据您的需求进行配置。
在怀疑组内出现问题时,是否有特定成员负责触发重新配置?
不,组内没有特定成员负责触发重新配置。
任何成员都可以怀疑存在问题。所有成员需要(自动)同意某个成员已经失败。一个成员负责将其从组中驱逐,触发重新配置。负责驱逐成员的成员不是您可以控制或设置的。
我可以将 Group Replication 用于分片吗?
Group Replication 旨在提供高可用性的副本集;数据和写入在组内的每个成员上都会复制。为了扩展超出单个系统所能提供的范围,您需要围绕多个 Group Replication 集构建编排和分片框架,其中每个副本集维护和管理总数据集的给定分片或分区。这种设置通常称为“分片集群”,允许您线性扩展读取和写入,而且没有限制。
如何在使用 SELinux 时使用 Group Replication?
如果启用了 SELinux,您可以使用 sestatus -v 进行验证,然后需要启用 Group Replication 通信端口的使用。请参阅 为 Group Replication 设置 TCP 端口上下文。
如何在使用 iptables 时使用 Group Replication?
如果启用了 iptables,那么您需要为机器之间的通信打开 Group Replication 端口。要查看每台机器上当前的规则,请执行 iptables -L。假设配置的端口是 33061,在必要端口上启用通信,请执行 iptables -A INPUT -p tcp --dport 33061 -j ACCEPT。
如何恢复由组成员使用的复制通道的中继日志?
Group Replication 使用的复制通道的行为方式与异步源到副本复制中使用的复制通道相同,因此依赖于中继日志。在更改relay_log
变量或主机名更改时,可能会出现错误。请参阅 Section 19.2.4.1, “The Relay Log”以了解在此情况下的恢复过程。另外,在 Group Replication 中专门解决此问题的另一种方法是发出STOP GROUP_REPLICATION
语句,然后发出START GROUP_REPLICATION
语句重新启动实例。Group Replication 插件会再次创建group_replication_applier
通道。
Group Replication 为什么使用两个绑定地址?
Group Replication 使用两个绑定地址,以便在 SQL 地址(客户端用于与成员通信的地址)和group_replication_local_address
之间分割网络流量,成员内部使用该地址进行通信。例如,假设一个服务器有两个网络接口分配给网络地址203.0.113.1
和198.51.100.179
。在这种情况下,您可以通过设置group_replication_local_address=203.0.113.1:33061
来使用203.0.113.1:33061
作为内部组网络地址。然后您可以使用198.51.100.179
作为hostname
,3306
作为port
。客户端 SQL 应用程序将连接到198.51.100.179:3306
的成员。这使您可以在不同网络上配置不同的规则。同样,内部组通信可以与用于客户端应用程序的网络连接分开,以增加安全性。
Group Replication 如何使用网络地址和主机名?
Group Replication 使用成员之间的网络连接,因此其功能直接受到主机名和端口配置的影响。例如,Group Replication 的分布式恢复过程使用服务器的主机名和端口创建到现有组成员的连接。当成员加入组时,它会接收组成员信息,使用在performance_schema.replication_group_members
中列出的网络地址信息。该表中列出的成员之一被选为从组到加入成员的缺失数据的捐赠者。
这意味着使用主机名配置的任何值,例如 SQL 网络地址或组种子地址,必须是完全合格的名称,并且每个组成员都可以解析。例如,您可以通过 DNS 或正确配置的/etc/hosts
文件或其他本地进程来确保这一点。如果您想在服务器上配置MEMBER_HOST
值,请在将其加入组之前使用服务器上的--report-host
选项指定。
重要
分配的值直接使用,不受skip_name_resolve
系统变量的影响。
要在服务器上配置MEMBER_PORT
,请使用report_port
系统变量指定。
为什么服务器上的自增设置发生了变化?
当在服务器上启动 Group Replication 时,auto_increment_increment
的值会更改为group_replication_auto_increment_increment
的值,默认为 7,并且auto_increment_offset
的值会更改为服务器 ID。当 Group Replication 停止时,更改会被还原。这些设置避免了在组成员上写入时选择重复的自增值,从而导致事务回滚。Group Replication 的默认自增值 7 代表可用值数量和复制组的允许最大大小(9 个成员)之间的平衡。
只有当auto_increment_increment
和auto_increment_offset
的值都已经被修改为默认值 1 时,更改才会生效并回滚。如果它们的值已经从默认值修改过,Group Replication 不会改变它们。从 MySQL 8.0 开始,当 Group Replication 处于单主模式时,系统变量也不会被修改,只有一个服务器进行写入。
如何找到主服务器?
如果组在单主模式下运行,找出哪个成员是主要的可能很有用。请参阅 Section 20.1.3.1.2, “Finding the Primary”
第二十一章 MySQL Shell
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-userguide.html
MySQL Shell 是用于 MySQL 服务器的高级客户端和代码编辑器。除了提供的 SQL 功能外,类似于mysql,MySQL Shell 还提供了 JavaScript 和 Python 的脚本功能,并包括用于与 MySQL 交互的 API。MySQL Shell 是一个可以单独安装的组件。
以下讨论简要描述了 MySQL Shell 的功能。有关更多信息,请参阅 MySQL Shell 手册,网址为dev.mysql.com/doc/mysql-shell/en/
。
MySQL Shell 包括以下用 JavaScript 和 Python 实现的 API,您可以使用这些 API 开发与 MySQL 交互的代码。
- 当 MySQL Shell 连接到 MySQL 服务器使用 X 协议时,X DevAPI 使开发人员能够同时处理关系型和文档数据。这使您可以将 MySQL 用作文档存储,有时被称为“使用 NoSQL”。有关更多信息,请参阅第二十二章,将 MySQL 用作文档存储。有关 X DevAPI 的概念和用法的文档,请参阅《X DevAPI 用户指南》。
- AdminAPI 使数据库管理员能够使用 InnoDB Cluster,为基于 InnoDB 的 MySQL 数据库提供了高可用性和可伸缩性的集成解决方案,而无需高级 MySQL 专业知识。AdminAPI 还包括对 InnoDB ReplicaSet 的支持,它使您能够以类似于 InnoDB Cluster 的方式管理运行异步 GTID 基于复制的一组 MySQL 实例。此外,AdminAPI 使 MySQL Router 的管理更加简单,包括与 InnoDB Cluster 和 InnoDB ReplicaSet 的集成。请参阅 MySQL AdminAPI。
MySQL Shell 有两个版本,社区版和商业版。社区版免费提供。商业版提供额外的企业功能,成本低廉。
第二十二章 使用 MySQL 作为文档存储
原文:
dev.mysql.com/doc/refman/8.0/en/document-store.html
目录
22.1 MySQL 文档存储的接口
22.2 文档存储概念
22.3 JavaScript 快速入门指南:MySQL Shell 文档存储
22.3.1 MySQL Shell
22.3.2 下载并导入 world_x 数据库
22.3.3 文档和集合
22.3.4 关系表
22.3.5 表格中的文档
22.4 Python 快速入门指南:MySQL Shell 文档存储
22.4.1 MySQL Shell
22.4.2 下载并导入 world_x 数据库
22.4.3 文档和集合
22.4.4 关系表
22.4.5 表格中的文档
22.5 X 插件
22.5.1 检查 X 插件安装
22.5.2 禁用 X 插件
22.5.3 使用加密连接与 X 插件
22.5.4 使用 X 插件与缓存 SHA-2 认证插件
22.5.5 使用 X 插件进行连接压缩
22.5.6 X 插件选项和变量
22.5.7 监控 X 插件
本章介绍了一种与 MySQL 作为文档存储一起工作的替代方式,有时被称为“使用 NoSQL”。如果您打算以传统(SQL)方式使用 MySQL,那么本章可能与您无关。
传统上,诸如 MySQL 这样的关系型数据库通常要求在存储文档之前定义模式。本节描述的功能使您能够将 MySQL 用作文档存储,这是一种无模式、因此是模式灵活的文档存储系统。例如,当您创建描述产品的文档时,您无需知道和定义任何产品的所有可能属性,就可以存储和操作文档。这与在关系型数据库中工作并将产品存储在表中有所不同,因为在向数据库添加任何产品之前,必须知道和定义表的所有列。本章描述的功能使您能够选择如何配置 MySQL,仅使用文档存储模型,或将文档存储模型的灵活性与关系模型的强大功能结合起来。
要将 MySQL 用作文档存储,您需要使用以下服务器功能:
- X 插件使 MySQL 服务器能够使用 X 协议与客户端通信,这是将 MySQL 用作文档存储的先决条件。从 MySQL 8.0 开始,X 插件在 MySQL 服务器中默认启用。有关验证 X 插件安装、配置和监视的说明,请参阅第 22.5 节,“X 插件”。
- X 协议支持 CRUD 和 SQL 操作,通过 SASL 进行身份验证,允许流式传输(流水线处理)命令,并且在协议和消息层面是可扩展的。与 X 协议兼容的客户端包括 MySQL Shell 和 MySQL 8.0 连接器。
- 使用 X 协议与 MySQL 服务器通信的客户端可以使用 X DevAPI 来开发应用程序。X DevAPI 提供了一个现代的编程接口,设计简单而强大,支持已建立的行业标准概念。本章介绍如何在 MySQL Shell 中作为客户端使用 X DevAPI 的 JavaScript 或 Python 实现。详细教程请参阅 X DevAPI 用户指南。
22.1 MySQL 文档存储接口
原文:
dev.mysql.com/doc/refman/8.0/en/document-store-interfaces.html
要将 MySQL 作为文档存储使用,您需要使用专用组件和支持与 MySQL 服务器通信的客户端来开发基于文档的应用程序。
- 以下 MySQL 产品支持 X 协议,并允许您在选择的语言中使用 X DevAPI 开发与作为文档存储的 MySQL 服务器通信的应用程序:
- MySQL Shell(提供 JavaScript 和 Python 中 X DevAPI 的实现)
- Connector/C
- Connector/J
- Connector/Node.js
- Connector/NET
- Connector/Python
- MySQL Shell 是一个交互式界面,支持 JavaScript、Python 或 SQL 模式的 MySQL。您可以使用 MySQL Shell 来原型应用程序,执行查询和更新数据。安装 MySQL Shell 包含下载和安装 MySQL Shell 的说明。
- 本章中的快速入门指南(教程)将帮助您开始使用 MySQL Shell 与 MySQL 作为文档存储。 JavaScript 的快速入门指南在这里:第 22.3 节,“JavaScript 快速入门指南:用于文档存储的 MySQL Shell”。 Python 的快速入门指南在这里:第 22.4 节,“Python 快速入门指南:用于文档存储的 MySQL Shell”。
- MySQL Shell 用户指南在 MySQL Shell 8.0 提供了关于配置和使用 MySQL Shell 的详细信息。
22.2 文档存储概念
原文:
dev.mysql.com/doc/refman/8.0/en/document-store-concepts.html
本节解释了在使用 MySQL 作为文档存储时引入的概念。
- JSON 文档
- 集合
- CRUD 操作
JSON 文档
JSON 文档是由键值对组成的数据结构,是使用 MySQL 作为文档存储的基本结构。例如,world_x 模式(本章后面安装)包含这个文档:
代码语言:javascript复制{
"GNP": 4834,
"_id": "00005de917d80000000000000023",
"Code": "BWA",
"Name": "Botswana",
"IndepYear": 1966,
"geography": {
"Region": "Southern Africa",
"Continent": "Africa",
"SurfaceArea": 581730
},
"government": {
"HeadOfState": "Festus G. Mogae",
"GovernmentForm": "Republic"
},
"demographics": {
"Population": 1622000,
"LifeExpectancy": 39.29999923706055
}
}
这份文档显示,键的值可以是简单的数据类型,比如整数或字符串,也可以包含其他文档、数组和文档列表。例如,geography
键的值由多个键值对组成。JSON 文档在 MySQL 中内部表示为二进制 JSON 对象,通过JSON
MySQL 数据类型。
文档与传统关系数据库中的表格之间最重要的区别在于,文档的结构不需要提前定义,并且一个集合可以包含具有不同结构的多个文档。另一方面,关系表要求定义其结构,并且表中的所有行必须包含相同的列。
集合
集合是用于在 MySQL 数据库中存储 JSON 文档的容器。应用程序通常针对文档集合运行操作,例如查找特定文档。
CRUD 操作
可以针对集合执行的四个基本操作是创建(Create)、读取(Read)、更新(Update)和删除(Delete)(CRUD)。在 MySQL 中,这意味着:
- 创建一个新文档(插入或添加)
- 读取一个或多个文档(查询)
- 更新一个或多个文档
- 删除一个或多个文档
22.3 JavaScript 快速入门指南:用于文档存储的 MySQL Shell
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript.html
22.3.1 MySQL Shell
22.3.2 下载和导入 world_x 数据库
22.3.3 文档和集合
22.3.4 关系表
22.3.5 表中的文档
本快速入门指南提供了使用 MySQL Shell 与文档存储应用程序进行交互原型设计的指令。该指南包括以下主题:
- MySQL 功能、MySQL Shell 和
world_x
示例模式的介绍。 - 操作以管理集合和文档。
- 操作以管理关系表。
- 适用于表中文档的操作。
要按照这个快速入门指南,您需要安装了 X 插件的 MySQL 服务器,默认情况下在 8.0 中,并且使用 MySQL Shell 作为客户端。MySQL Shell 8.0 提供了关于 MySQL Shell 更深入的信息。文档存储使用 X DevAPI 访问,并且 MySQL Shell 在 JavaScript 和 Python 中都提供了这个 API。
相关信息
- MySQL Shell 8.0 提供了关于 MySQL Shell 更深入的信息。
- 有关本快速入门指南中使用的工具的更多信息,请参阅安装 MySQL Shell 和第 22.5 节,“X 插件”。
- X DevAPI 用户指南提供了更多使用 X DevAPI 开发使用文档存储的应用程序的示例。
- 还提供了一个 Python 快速入门指南。
22.3.1 MySQL Shell
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-shell.html
本快速入门指南假定您对 MySQL Shell 有一定的了解。以下部分是一个高级概述,请参阅 MySQL Shell 文档以获取更多信息。MySQL Shell 是到 MySQL 服务器的统一脚本接口。它支持 JavaScript 和 Python 脚本。JavaScript 是默认处理模式。
启动 MySQL Shell
安装并启动 MySQL 服务器后,将 MySQL Shell 连接到服务器实例。您需要知道要连接的 MySQL 服务器实例的地址。要将实例用作文档存储,服务器实例必须安装 X 插件,并且您应该使用 X 协议连接到服务器。例如,要连接到默认 X 协议端口 33060 上的实例 ds1.example.com
,请使用网络字符串 *
user*@ds1.example.com:33060
。
提示
如果您使用经典的 MySQL 协议连接到实例,例如使用默认的port
3306,而不是mysqlx_port
,则无法使用本教程中展示的文档存储功能。例如,db
全局对象未被填充。要使用文档存储功能,请始终使用 X 协议连接。
如果 MySQL Shell 尚未运行,请打开一个终端窗口并输入:
代码语言:javascript复制mysqlsh *user*@ds1.example.com:33060/world_x
或者,如果 MySQL Shell 已在运行,请使用 connect
命令输入:
connect *user*@ds1.example.com:33060/world_x
您需要指定要将 MySQL Shell 连接到的 MySQL 服务器实例的地址。例如,在上一个示例中:
-
user
代表您的 MySQL 帐户的用户名。 -
ds1.example.com
是运行 MySQL 的服务器实例的主机名。请将其替换为您用作文档存储的 MySQL 服务器实例的主机名。 - 本会话的默认模式为
world_x
。有关设置world_x
模式的说明,请参见 Section 22.3.2, “下载和导入 world_x 数据库”。
有关更多信息,请参见 Section 6.2.5, “使用类似 URI 字符串或键值对连接到服务器”。
一旦 MySQL Shell 打开,mysql-js>
提示表示此会话的活动语言为 JavaScript。
mysql-js>
MySQL Shell 支持以下输入行编辑:
- 左箭头 和 右箭头 键在当前输入行内水平移动。
- 上箭头 和 下箭头 键在先前输入的行集中上下移动。
- Backspace 删除光标前的字符,输入新字符会在光标位置输入。
- Enter发送当前输入行到服务器。
获取 MySQL Shell 帮助
在命令解释器提示符处输入mysqlsh --help以获取命令行选项列表。
代码语言:javascript复制mysqlsh --help
在 MySQL Shell 提示符处输入help
以获取可用命令及其描述列表。
mysql-js> help
输入help
后跟命令名称以获取有关单个 MySQL Shell 命令的详细帮助。例如,要查看connect
命令的帮助,请输入:
mysql-js> help connect
退出 MySQL Shell
要退出 MySQL Shell,请输入以下命令:
代码语言:javascript复制mysql-js> quit
相关信息
- 查看交互式代码执行以了解 MySQL Shell 中交互式代码执行的工作原理。
- 查看使用 MySQL Shell 入门以了解会话和连接选项。
22.3.2 下载并导入 world_x 数据库
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-download.html
作为快速入门指南的一部分,提供了一个示例模式,称为world_x
模式。许多示例演示了使用此模式的文档存储功能。启动您的 MySQL 服务器,以便加载world_x
模式,然后按照以下步骤操作:
下载world_x-db.zip。
将安装归档文件提取到临时位置,例如/tmp/
。解压缩归档文件会生成一个名为world_x.sql
的单个文件。
将world_x.sql
文件导入到您的服务器。您可以选择:
在 SQL 模式下启动 MySQL Shell,并通过以下方式导入文件:
代码语言:javascript复制mysqlsh -u root --sql --file /tmp/world_x-db/world_x.sql
Enter password: ****
在运行时将 MySQL Shell 设置为 SQL 模式,并通过以下方式源化模式文件:
代码语言:javascript复制sql
Switching to SQL mode... Commands end with ;
source /tmp/world_x-db/world_x.sql
将/tmp/
替换为系统中world_x.sql
文件的路径。如果提示,请输入密码。只要帐户具有创建新模式的权限,非 root 帐户就可以使用。
world_x 模式
world_x
示例模式包含以下 JSON 集合和关系表:
- 集合
countryinfo
:关于世界各国的信息。
- 表
-
country
:关于世界各国的基本信息。 -
city
:关于这些国家中一些城市的信息。 -
countrylanguage
:每个国家使用的语言。
-
相关信息
- MySQL Shell 会话解释了会话类型。
22.3.3 文档和集合
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-documents-collections.html
22.3.3.1 创建、列出和删除集合
22.3.3.2 使用集合
22.3.3.3 查找文档
22.3.3.4 修改文档
22.3.3.5 删除文档
22.3.3.6 创建和删除索引
当您将 MySQL 用作文档存储时,集合是模式内的容器,您可以创建、列出和删除。集合包含您可以添加、查找、更新和删除的 JSON 文档。
本节示例使用world_x
模式中的countryinfo
集合。有关设置world_x
模式的说明,请参见第 22.3.2 节,“下载和导入 world_x 数据库”。
文档
在 MySQL 中,文档被表示为 JSON 对象。在内部,它们以一种高效的二进制格式存储,可以实现快速查找和更新。
JavaScript 的简单文档格式:
代码语言:javascript复制{field1: "value", field2 : 10, "field 3": null}
一个文档数组由一组由逗号分隔并包含在[
和]
字符中的文档组成。
JavaScript 的简单文档数组:
代码语言:javascript复制[{"Name": "Aruba", "Code:": "ABW"}, {"Name": "Angola", "Code:": "AGO"}]
MySQL 支持 JSON 文档中的以下 JavaScript 值类型:
- 数字(整数和浮点数)
- 字符串
- 布尔值(False 和 True)
- null
- 更多 JSON 值的数组
- 更多 JSON 值的嵌套(或嵌入)对象
集合
集合是用于共享目的和可能共享一个或多个索引的文档的容器。每个集合都有一个唯一的名称,并存在于单个模式中。
术语模式等同于数据库,意味着一组数据库对象,而不是用于强制数据结构和约束的关系模式。模式不会对集合中的文档强制执行一致性。
在这个快速入门指南中:
- 基本对象包括:
对象形式描述
dbdb
是分配给当前活动模式的全局变量。当您想对模式运行操作时,例如检索集合,您可以使用db
变量可用的方法。db.getCollections()
db.getCollections() 返回模式中集合的列表。使用列表获取对集合对象的引用,对其进行迭代等。 - 由集合范围的基本操作包括:
操作形式描述
db.*
name*.add()
add() 方法将一个或多个文档插入到指定集合中。db.*
name*.find()
find() 方法返回指定集合中的一些或所有文档。db.*
name*.modify()
modify() 方法更新指定集合中的文档。db.*
name*.remove()
remove() 方法从指定集合中删除一个或多个文档。
相关信息
- 查看 Working with Collections 以获取一般概述。
- CRUD EBNF Definitions 提供了完整的操作列表。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-collections-operations.html
22.3.3.1 创建、列出和删除集合
在 MySQL Shell 中,您可以创建新集合,获取模式中现有集合的列表,并从模式中删除一个已存在的集合。集合名称区分大小写,每个集合名称必须是唯一的。
确认模式
要显示分配给模式变量的值,请执行:
代码语言:javascript复制mysql-js> db
如果模式值不是Schema:world_x
,则通过执行以下命令设置db
变量:
mysql-js> use world_x
创建一个集合
要在现有模式中创建一个新集合,使用db
对象的createCollection()
方法。以下示例在world_x
模式中创建一个名为flags
的集合。
mysql-js> db.createCollection("flags")
该方法返回一个集合对象。
代码语言:javascript复制<Collection:flags>
列出集合
要显示world_x
模式中的所有集合,请使用db
对象的getCollections()
方法。由当前连接到的服务器返回的集合将显示在括号之间。
mysql-js> db.getCollections()
[
<Collection:countryinfo>,
<Collection:flags>
]
删除一个集合
要从模式中删除一个已存在的集合,使用db
对象的dropCollection()
方法。例如,要从当前模式中删除flags
集合,执行:
mysql-js> db.dropCollection("flags")
dropCollection()
方法也可用于在 MySQL Shell 中从模式中删除关系表。
相关信息
- 查看集合对象以获取更多示例。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-collections-add.html
22.3.3.2 与集合一起工作
要在模式中使用集合,请使用db
全局对象访问当前模式。在此示例中,我们使用之前导入的world_x
模式和countryinfo
集合。因此,您发出的操作格式为db.*
collection_name*.operation
,其中*collection_name
*是执行操作的集合的名称。在以下示例中,操作是针对countryinfo
集合执行的。
添加文档
使用add()
方法将一个文档或文档列表插入到现有集合中。将以下文档插入到countryinfo
集合中。由于这是多行内容,请按两次Enter键以插入文档。
mysql-js> db.countryinfo.add(
{
GNP: .6,
IndepYear: 1967,
Name: "Sealand",
Code: "SEA",
demographics: {
LifeExpectancy: 79,
Population: 27
},
geography: {
Continent: "Europe",
Region: "British Islands",
SurfaceArea: 193
},
government: {
GovernmentForm: "Monarchy",
HeadOfState: "Michael Bates"
}
}
)
该方法返回操作的状态。您可以通过搜索文档来验证操作。例如:
代码语言:javascript复制mysql-js> db.countryinfo.find("Name = 'Sealand'")
{
"GNP": 0.6,
"_id": "00005e2ff4af00000000000000f4",
"Name": "Sealand",
"Code:": "SEA",
"IndepYear": 1967,
"geography": {
"Region": "British Islands",
"Continent": "Europe",
"SurfaceArea": 193
},
"government": {
"HeadOfState": "Michael Bates",
"GovernmentForm": "Monarchy"
},
"demographics": {
"Population": 27,
"LifeExpectancy": 79
}
}
请注意,除了在添加文档时指定的字段之外,还有一个字段,即_id
。每个文档都需要一个名为_id
的标识符字段。_id
字段的值在同一集合中的所有文档中必须是唯一的。在 MySQL 8.0.11 及更高版本中,文档 ID 由服务器生成,而不是客户端生成,因此 MySQL Shell 不会自动设置_id
值。如果文档不包含_id
字段,MySQL 8.0.11 或更高版本的服务器会设置_id
值。在较早的 8.0 版本或 5.7 版本的 MySQL 服务器中,在这种情况下不会设置_id
值,因此您必须明确指定它。如果不指定,MySQL Shell 将返回错误 5115 文档缺少必需字段。有关更多信息,请参见理解文档 ID。
相关信息
- 查看 CollectionAddFunction 以获取完整的语法定义。
- 查看理解文档 ID。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-documents-find.html
22.3.3.3 查找文档
您可以使用find()
方法查询并返回模式中集合中的文档。MySQL Shell 提供额外的方法与find()
方法一起使用,以过滤和排序返回的文档。
MySQL 提供以下运算符来指定搜索条件:OR
(||
)、AND
(&&
)、XOR
、IS
、NOT
、BETWEEN
、IN
、LIKE
、!=
、<>
、>
、>=
、<
、<=
、&
、|
、<<
、>>
、
、-
、*
、/
、~
和%
。
查找集合中的所有文档
要返回集合中的所有文档,请使用不指定搜索条件的find()
方法。例如,以下操作返回countryinfo
集合中的所有文档。
mysql-js> db.countryinfo.find()
[
{
"GNP": 828,
"Code:": "ABW",
"Name": "Aruba",
"IndepYear": null,
"geography": {
"Continent": "North America",
"Region": "Caribbean",
"SurfaceArea": 193
},
"government": {
"GovernmentForm": "Nonmetropolitan Territory of The Netherlands",
"HeadOfState": "Beatrix"
}
"demographics": {
"LifeExpectancy": 78.4000015258789,
"Population": 103000
},
...
}
]
240 documents in set (0.00 sec)
该方法生成包含操作信息以及集合中所有文档的结果。
空集(无匹配文档)返回以下信息:
代码语言:javascript复制Empty set (0.00 sec)
过滤搜索
您可以使用find()
方法包含搜索条件。形成搜索条件的表达式语法与传统 MySQL 第十四章,函数和运算符相同。您必须将所有表达式括在引号中。为简洁起见,一些示例未显示输出。
一个简单的搜索条件可能包括Name
字段和我们知道在文档中的值。以下示例返回单个文档:
mysql-js> db.countryinfo.find("Name = 'Australia'")
[
{
"GNP": 351182,
"Code:": "AUS",
"Name": "Australia",
"IndepYear": 1901,
"geography": {
"Continent": "Oceania",
"Region": "Australia and New Zealand",
"SurfaceArea": 7741220
},
"government": {
"GovernmentForm": "Constitutional Monarchy, Federation",
"HeadOfState": "Elisabeth II"
}
"demographics": {
"LifeExpectancy": 79.80000305175781,
"Population": 18886000
},
}
]
以下示例搜索所有人均 GNP 高于 5000 亿美元的国家。countryinfo
集合以百万为单位衡量 GNP。
mysql-js> db.countryinfo.find("GNP > 500000")
...[*output removed*]
10 documents in set (0.00 sec)
下面查询中的人口字段嵌入在 demographics 对象中。要访问嵌入字段,请在 demographics 和 Population 之间使用句点来标识关系。文档和字段名称区分大小写。
代码语言:javascript复制mysql-js> db.countryinfo.find("GNP > 500000 and demographics.Population < 100000000")
...[*output removed*]
6 documents in set (0.00 sec)
下面表达式中的算术运算符用于查询人均 GNP 高于$30000 的国家。搜索条件可以包括算术运算符和大多数 MySQL 函数。
注意
countryinfo
集合中有七个文档的人口值为零。因此,在输出末尾会出现警告消息。
mysql-js> db.countryinfo.find("GNP*1000000/demographics.Population > 30000")
...[*output removed*]
9 documents in set, 7 warnings (0.00 sec)
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
Warning (Code 1365): Division by 0
您可以使用bind()
方法将值与搜索条件分离。例如,不要将硬编码的国家名称指定为条件,而是用以字母开头的名称后跟冒号组成的命名占位符替换。然后使用bind(*
占位符*, *
值*)
方法如下:
mysql-js> db.countryinfo.find("Name = :country").bind("country", "Italy")
{
"GNP": 1161755,
"_id": "00005de917d8000000000000006a",
"Code": "ITA",
"Name": "Italy",
"Airports": [],
"IndepYear": 1861,
"geography": {
"Region": "Southern Europe",
"Continent": "Europe",
"SurfaceArea": 301316
},
"government": {
"HeadOfState": "Carlo Azeglio Ciampi",
"GovernmentForm": "Republic"
},
"demographics": {
"Population": 57680000,
"LifeExpectancy": 79
}
}
1 document in set (0.01 sec)
提示
在程序内,绑定使您能够在表达式中指定占位符,在执行之前用值填充,并且可以从适当的自动转义中受益。
始终使用绑定来清理输入。避免使用字符串拼接在查询中引入值,这可能会产生无效输入,并且在某些情况下可能会导致安全问题。
您可以使用占位符和bind()
方法创建保存的搜索,然后可以使用不同的值调用它们。例如,为一个国家创建一个保存的搜索:
mysql-js> var myFind = db.countryinfo.find("Name = :country")
mysql-js> myFind.bind('country', 'France')
{
"GNP": 1424285,
"_id": "00005de917d80000000000000048",
"Code": "FRA",
"Name": "France",
"IndepYear": 843,
"geography": {
"Region": "Western Europe",
"Continent": "Europe",
"SurfaceArea": 551500
},
"government": {
"HeadOfState": "Jacques Chirac",
"GovernmentForm": "Republic"
},
"demographics": {
"Population": 59225700,
"LifeExpectancy": 78.80000305175781
}
}
1 document in set (0.0028 sec)
mysql-js> myFind.bind('country', 'Germany')
{
"GNP": 2133367,
"_id": "00005de917d80000000000000038",
"Code": "DEU",
"Name": "Germany",
"IndepYear": 1955,
"geography": {
"Region": "Western Europe",
"Continent": "Europe",
"SurfaceArea": 357022
},
"government": {
"HeadOfState": "Johannes Rau",
"GovernmentForm": "Federal Republic"
},
"demographics": {
"Population": 82164700,
"LifeExpectancy": 77.4000015258789
}
}
1 document in set (0.0026 sec)
项目结果
您可以返回文档的特定字段,而不是返回所有字段。以下示例返回符合搜索条件的countryinfo
集合中所有文档的 GNP 和 Name 字段。
使用fields()
方法传递要返回的字段列表。
mysql-js> db.countryinfo.find("GNP > 5000000").fields(["GNP", "Name"])
[
{
"GNP": 8510700,
"Name": "United States"
}
]
1 document in set (0.00 sec)
此外,您可以修改返回的文档——添加、重命名、嵌套甚至计算新字段值——使用描述要返回的文档的表达式。例如,使用以下表达式更改字段的名称以仅返回两个文档。
代码语言:javascript复制mysql-js> db.countryinfo.find().fields(
mysqlx.expr('{"Name": upper(Name), "GNPPerCapita": GNP*1000000/demographics.Population}')).limit(2)
{
"Name": "ARUBA",
"GNPPerCapita": 8038.834951456311
}
{
"Name": "AFGHANISTAN",
"GNPPerCapita": 263.0281690140845
}
限制、排序和跳过结果
您可以应用limit()
、sort()
和skip()
方法来管理find()
方法返回的文档数量和顺序。
要指定结果集中包含的文档数量,请将limit()
方法附加到find()
方法,并指定一个值。以下查询返回countryinfo
集合中的前五个文档。
mysql-js> db.countryinfo.find().limit(5)
... [*output removed*]
5 documents in set (0.00 sec)
要为结果指定顺序,请将sort()
方法附加到find()
方法。将一个或多个要按其排序的字段列表传递给sort()
方法,并根据需要选择降序(desc
)或升序(asc
)属性。升序顺序是默认的顺序类型。
例如,以下查询按独立年份字段对所有文档进行排序,然后按降序返回前八个文档。
代码语言:javascript复制mysql-js> db.countryinfo.find().sort(["IndepYear desc"]).limit(8)
... [*output removed*]
8 documents in set (0.00 sec)
默认情况下,limit()
方法从集合中的第一个文档开始。您可以使用skip()
方法更改起始文档。例如,要忽略第一个文档并返回符合条件的下一个八个文档,请将值 1 传递给skip()
方法。
mysql-js> db.countryinfo.find().sort(["IndepYear desc"]).limit(8).skip(1)
... [*output removed*]
8 documents in set (0.00 sec)
相关信息
- MySQL 参考手册提供了有关函数和运算符的详细文档。
- 请参阅 CollectionFindFunction 获取完整的语法定义。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-documents-modify.html
22.3.3.4 修改文档
您可以使用modify()
方法更新集合中的一个或多个文档。X DevAPI 提供了与modify()
方法一起使用的其他方法,以:
- 在文档内设置和取消设置字段。
- 追加、插入和删除数组。
- 绑定、限制和排序要修改的文档。
设置和取消设置文档字段
modify()
方法通过过滤集合以仅包括要修改的文档,然后将您指定的操作应用于这些文档来工作。
在下面的示例中,modify()
方法使用搜索条件标识要更改的文档,然后set()
方法替换了嵌套的 demographics 对象中的两个值。
mysql-js> db.countryinfo.modify("Code = 'SEA'").set(
"demographics", {"LifeExpectancy": 78, "Population": 28})
修改文档后,请使用find()
方法验证更改。
要从文档中删除内容,请使用modify()
和unset()
方法。例如,以下查询从符合搜索条件的文档中删除了 GNP。
mysql-js> db.countryinfo.modify("Name = 'Sealand'").unset("GNP")
使用find()
方法验证更改。
mysql-js> db.countryinfo.find("Name = 'Sealand'")
{
"_id": "00005e2ff4af00000000000000f4",
"Name": "Sealand",
"Code:": "SEA",
"IndepYear": 1967,
"geography": {
"Region": "British Islands",
"Continent": "Europe",
"SurfaceArea": 193
},
"government": {
"HeadOfState": "Michael Bates",
"GovernmentForm": "Monarchy"
},
"demographics": {
"Population": 27,
"LifeExpectancy": 79
}
}
追加、插入和删除数组
要向数组字段追加元素,或在数组中插入、删除元素,请使用arrayAppend()
、arrayInsert()
或arrayDelete()
方法。以下示例修改了countryinfo
集合以启用对国际机场的跟踪。
第一个示例使用modify()
和set()
方法在所有文档中创建一个新的 Airports 字段。
注意
在修改文档时要小心,如果没有指定搜索条件,会修改集合中的所有文档。
代码语言:javascript复制mysql-js> db.countryinfo.modify("true").set("Airports", [])
添加了 Airports 字段后,下一个示例使用arrayAppend()
方法向其中一个文档添加新机场。在下面的示例中,$.Airports代表当前文档的 Airports 字段。
mysql-js> db.countryinfo.modify("Name = 'France'").arrayAppend("$.Airports", "ORY")
使用find()
查看更改。
mysql-js> db.countryinfo.find("Name = 'France'")
{
"GNP": 1424285,
"_id": "00005de917d80000000000000048",
"Code": "FRA",
"Name": "France",
"Airports": [
"ORY"
],
"IndepYear": 843,
"geography": {
"Region": "Western Europe",
"Continent": "Europe",
"SurfaceArea": 551500
},
"government": {
"HeadOfState": "Jacques Chirac",
"GovernmentForm": "Republic"
},
"demographics": {
"Population": 59225700,
"LifeExpectancy": 78.80000305175781
}
}
要在数组中的不同位置插入元素,请使用arrayInsert()
方法指定要插入的索引路径表达式。在这种情况下,索引为 0,即数组中的第一个元素。
mysql-js> db.countryinfo.modify("Name = 'France'").arrayInsert("$.Airports[0]", "CDG")
要从数组中删除元素,必须向arrayDelete()
方法传递要删除的元素的索引。
mysql-js> db.countryinfo.modify("Name = 'France'").arrayDelete("$.Airports[1]")
相关信息
- MySQL 参考手册提供了帮助您搜索和修改 JSON 值的说明。
- 查看 CollectionModifyFunction 以获取完整的语法定义。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-documents-remove.html
22.3.3.5 删除文档
您可以使用remove()
方法从模式中的集合中删除一些或所有文档。X DevAPI 提供了与remove()
方法一起使用的其他方法,用于过滤和排序要删除的文档。
使用条件删除文档
以下示例向remove()
方法传递了搜索条件。匹配条件的所有文档都将从countryinfo
集合中删除。在此示例中,有一个文档符合条件。
mysql-js> db.countryinfo.remove("Code = 'SEA'")
删除第一个文档
要删除countryinfo
集合中的第一个文档,请使用值为 1 的limit()
方法。
mysql-js> db.countryinfo.remove("true").limit(1)
删除订单中的最后一个文档
以下示例按国家名称删除了countryinfo
集合中的最后一个文档。
mysql-js> db.countryinfo.remove("true").sort(["Name desc"]).limit(1)
删除集合中的所有文档
您可以删除集合中的所有文档。要这样做,请使用remove("true")
方法,而不指定搜索条件。
注意
在删除文档时,请谨慎操作,不指定搜索条件会删除集合中的所有文档。
或者,使用db.drop_collection('countryinfo')
操作来删除countryinfo
集合。
相关信息
- 请参阅 CollectionRemoveFunction 以获取完整的语法定义。
- 请参阅第 22.3.2 节,“下载和导入 world_x 数据库”以获取重新创建
world_x
模式的说明。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-indexes-create.html
22.3.3.6 创建和删除索引
索引用于快速查找具有特定字段值的文档。没有索引,MySQL 必须从第一个文档开始,然后读取整个集合以查找相关字段。集合越大,成本越高。如果集合很大且对特定字段的查询很常见,则考虑在文档内的特定字段上创建索引。
例如,以下查询在 Population 字段上使用索引性能更好:
代码语言:javascript复制mysql-js> db.countryinfo.find("demographics.Population < 100")
...[*output removed*]
8 documents in set (0.00 sec)
createIndex()
方法创建一个可以用 JSON 文档定义的索引,该文档指定要使用的字段。本节是索引的高级概述。有关更多信息,请参见索引集合。
添加非唯一索引
要创建非唯一索引,请将索引名称和索引信息传递给createIndex()
方法。禁止重复索引名称。
以下示例指定了一个名为popul
的索引,针对demographics
对象中的Population
字段定义,索引为Integer
数值。最后一个参数指示字段是否应该需要NOT NULL
约束。如果值为false
,则字段可以包含NULL
值。索引信息是一个包含一个或多个字段详细信息的 JSON 文档。每个字段定义必须包括字段的完整文档路径,并指定字段的类型。
mysql-js> db.countryinfo.createIndex("popul", {fields:
[{field: '$.demographics.Population', type: 'INTEGER'}]})
在这里,索引是使用整数数值创建的。还有其他选项可用,包括用于 GeoJSON 数据的选项。您还可以指定索引类型,这里省略了,因为默认类型“index”是适当的。
添加唯一索引
要创建唯一索引,请将索引名称、索引定义和索引类型“unique”传递给createIndex()
方法。此示例显示了在国家名称("Name"
)上创建的唯一索引,这是countryinfo
集合中另一个常见字段进行索引。在索引字段描述中,"TEXT(40)"
表示要索引的字符数,"required": True
指定字段必须存在于文档中。
mysql-js> db.countryinfo.createIndex("name",
{"fields": [{"field": "$.Name", "type": "TEXT(40)", "required": true}], "unique": true})
删除索引
要删除索引,请将要删除的索引名称传递给dropIndex()
方法。例如,您可以按如下方式删除“popul”索引:
mysql-js> db.countryinfo.dropIndex("popul")
相关信息
- 有关更多信息,请参见索引集合。
- 有关定义索引的 JSON 文档的更多信息,请参见定义索引。
- 有关完整语法定义,请参见集合索引管理函数。
22.3.4 关系表
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-relational-tables.html
22.3.4.1 向表中插入记录
22.3.4.2 选择表
22.3.4.3 更新表
22.3.4.4 删除表
您还可以使用 X DevAPI 来处理关系表。在 MySQL 中,每个关系表都与特定的存储引擎相关联。本节中的示例使用 world_x
模式中的 InnoDB
表。
确认模式
要显示分配给 db
全局变量的模式,请发出 db
。
mysql-js> db
<Schema:world_x>
如果返回值不是Schema:world_x
,则将db
变量设置如下:
mysql-js> use world_x
Schema `world_x` accessible through db.
显示所有表
要显示 world_x
模式中的所有关系表,请在 db
对象上使用 getTables()
方法。
mysql-js> db.getTables()
{
"city": <Table:city>,
"country": <Table:country>,
"countrylanguage": <Table:countrylanguage>
}
基本表操作
按表范围的基本操作包括:
操作形式 | 描述 |
---|---|
db.*name*.insert() | insert() 方法向指定表中插入一个或多个记录。 |
db.*name*.select() | select() 方法返回指定表中的一些或所有记录。 |
db.*name*.update() | update() 方法更新指定表中的记录。 |
db.*name*.delete() | delete() 方法从指定表中删除一个或多个记录。 |
相关信息
- 有关处理关系表的更多信息,请参阅 处理关系表。
- CRUD EBNF 定义 提供了操作的完整列表。
- 请参阅 第 22.3.2 节“下载并导入 world_x 数据库” 以获取设置
world_x
模式示例的说明。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-table-insert.html
22.3.4.1 插入记录到表中
你可以使用insert()
方法与values()
方法将记录插入到现有的关系表中。insert()
方法接受单个列或表中的所有列。使用一个或多个values()
方法指定要插入的值。
插入完整记录
要插入完整记录,将表中的所有列传递给insert()
方法。然后对values()
方法传递表中每列的一个值。例如,要向world_x
模式中的 city 表添加新记录,请插入以下记录并按两次Enter。
mysql-js> db.city.insert("ID", "Name", "CountryCode", "District", "Info").values(
None, "Olympia", "USA", "Washington", '{"Population": 5000}')
city 表有五列:ID、Name、CountryCode、District 和 Info。每个值必须与它所代表的列的数据类型匹配。
插入部分记录
以下示例将值插入到 city 表的 ID、Name 和 CountryCode 列中。
代码语言:javascript复制mysql-js> db.city.insert("ID", "Name", "CountryCode").values(
None, "Little Falls", "USA").values(None, "Happy Valley", "USA")
当你使用insert()
方法指定列时,值的数量必须与列的数量相匹配。在前面的示例中,你必须提供三个值以匹配指定的三列。
相关信息
- 查看 TableInsertFunction 以获取完整的语法定义。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-table-select.html
22.3.4.2 选择表
您可以使用select()
方法从数据库中的表中查询并返回记录。X DevAPI 提供了额外的方法与select()
方法一起使用,以过滤和排序返回的记录。
MySQL 提供以下运算符来指定搜索条件:OR
(||
)、AND
(&&
)、XOR
、IS
、NOT
、BETWEEN
、IN
、LIKE
、!=
、<>
、>
、>=
、<
、<=
、&
、|
、<<
、>>
、
、-
、*
、/
、~
和%
。
选择所有记录
要发出返回现有表中所有记录的查询,请使用不指定搜索条件的select()
方法。以下示例从world_x
数据库中的 city 表中选择所有记录。
注意
限制在交互式语句中使用空的select()
方法。始终在应用程序代码中使用显式列名选择。
mysql-js> db.city.select()
------ ------------ ------------- ------------ -------------------------
| ID | Name | CountryCode | District | Info |
------ ------------ ------------- ------------ -------------------------
| 1 | Kabul | AFG | Kabol |{"Population": 1780000} |
| 2 | Qandahar | AFG | Qandahar |{"Population": 237500} |
| 3 | Herat | AFG | Herat |{"Population": 186800} |
... ... ... ... ...
| 4079 | Rafah | PSE | Rafah |{"Population": 92020} |
------ ------- ---- ------------- ------------ -------------------------
4082 rows in set (0.01 sec)
空集(没有匹配记录)返回以下信息:
代码语言:javascript复制Empty set (0.00 sec)
过滤搜索
要发出返回一组表列的查询,请使用select()
方法并在方括号之间指定要返回的列。此查询返回 city 表中的 Name 和 CountryCode 列。
mysql-js> db.city.select(["Name", "CountryCode"])
------------------- -------------
| Name | CountryCode |
------------------- -------------
| Kabul | AFG |
| Qandahar | AFG |
| Herat | AFG |
| Mazar-e-Sharif | AFG |
| Amsterdam | NLD |
... ...
| Rafah | PSE |
| Olympia | USA |
| Little Falls | USA |
| Happy Valley | USA |
------------------- -------------
4082 rows in set (0.00 sec)
要发出返回符合特定搜索条件的行的查询,请使用where()
方法包含这些条件。例如,以下示例返回以字母 Z 开头的城市的名称和国家代码。
mysql-js> db.city.select(["Name", "CountryCode"]).where("Name like 'Z%'")
------------------- -------------
| Name | CountryCode |
------------------- -------------
| Zaanstad | NLD |
| Zoetermeer | NLD |
| Zwolle | NLD |
| Zenica | BIH |
| Zagazig | EGY |
| Zaragoza | ESP |
| Zamboanga | PHL |
| Zahedan | IRN |
| Zanjan | IRN |
| Zabol | IRN |
| Zama | JPN |
| Zhezqazghan | KAZ |
| Zhengzhou | CHN |
... ...
| Zeleznogorsk | RUS |
------------------- -------------
59 rows in set (0.00 sec)
您可以使用bind()
方法将值与搜索条件分开。例如,不要使用"Name = ‘Z%’ "作为条件,而是用以字母开头的名称后跟冒号的命名占位符替换。然后在bind()
方法中包含占位符和值,如下所示:
mysql-js> db.city.select(["Name", "CountryCode"]).
where("Name like :name").bind("name", "Z%")
提示
在程序内,绑定使您能够在表达式中指定占位符,在执行之前用值填充,并且可以从适当的自动转义中受益。
始终使用绑定来清理输入。避免使用字符串连接在查询中引入值,这可能会产生无效输入,并且在某些情况下可能会导致安全问题。
项目结果
要使用AND
运算符发出查询,请在where()
方法中的搜索条件之间添加该运算符。
mysql-js> db.city.select(["Name", "CountryCode"]).where(
"Name like 'Z%' and CountryCode = 'CHN'")
---------------- -------------
| Name | CountryCode |
---------------- -------------
| Zhengzhou | CHN |
| Zibo | CHN |
| Zhangjiakou | CHN |
| Zhuzhou | CHN |
| Zhangjiang | CHN |
| Zigong | CHN |
| Zaozhuang | CHN |
... ...
| Zhangjiagang | CHN |
---------------- -------------
22 rows in set (0.01 sec)
要指定多个条件运算符,可以将搜索条件括在括号中以更改运算符优先级。以下示例演示了AND
和OR
运算符的放置位置。
mysql-js> db.city.select(["Name", "CountryCode"]).
where("Name like 'Z%' and (CountryCode = 'CHN' or CountryCode = 'RUS')")
------------------- -------------
| Name | CountryCode |
------------------- -------------
| Zhengzhou | CHN |
| Zibo | CHN |
| Zhangjiakou | CHN |
| Zhuzhou | CHN |
... ...
| Zeleznogorsk | RUS |
------------------- -------------
29 rows in set (0.01 sec)
限制、排序和偏移结果
您可以应用limit()
、orderBy()
和offSet()
方法来管理select()
方法返回的记录数量和顺序。
要指定结果集中包含的记录数,请将limit()
方法附加到select()
方法并指定一个值。例如,以下查询返回国家表中的前五条记录。
mysql-js> db.country.select(["Code", "Name"]).limit(5)
------ -------------
| Code | Name |
------ -------------
| ABW | Aruba |
| AFG | Afghanistan |
| AGO | Angola |
| AIA | Anguilla |
| ALB | Albania |
------ -------------
5 rows in set (0.00 sec)
要为结果指定顺序,请将orderBy()
方法附加到select()
方法。将一个或多个要排序的列的列表传递给orderBy()
方法,并根据需要选择降序(desc
)或升序(asc
)属性。升序是默认的排序类型。
例如,以下查询按照 Name 列对所有记录进行排序,然后以降序方式返回前三条记录。
代码语言:javascript复制mysql-js> db.country.select(["Code", "Name"]).orderBy(["Name desc"]).limit(3)
------ ------------
| Code | Name |
------ ------------
| ZWE | Zimbabwe |
| ZMB | Zambia |
| YUG | Yugoslavia |
------ ------------
3 rows in set (0.00 sec)
默认情况下,limit()
方法从表中的第一条记录开始。您可以使用offset()
方法来更改起始记录。例如,要忽略第一条记录并返回符合条件的接下来三条记录,请将值 1 传递给offset()
方法。
mysql-js> db.country.select(["Code", "Name"]).orderBy(["Name desc"]).limit(3).offset(1)
------ ------------
| Code | Name |
------ ------------
| ZMB | Zambia |
| YUG | Yugoslavia |
| YEM | Yemen |
------ ------------
3 rows in set (0.00 sec)
相关信息
- MySQL 参考手册提供了有关函数和运算符的详细文档。
- 查看 TableSelectFunction 以获取完整的语法定义。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-table-update.html
22.3.4.3 更新表
你可以使用update()
方法来修改表中的一个或多个记录。update()
方法通过过滤查询来仅包括需要更新的记录,然后对这些记录应用你指定的操作。
要在城市表中替换城市名称,将新的城市名称传递给set()
方法。然后,将要定位和替换的城市名称传递给where()
方法。以下示例将城市 Peking 替换为 Beijing。
mysql-js> db.city.update().set("Name", "Beijing").where("Name = 'Peking'")
使用select()
方法来验证更改。
mysql-js> db.city.select(["ID", "Name", "CountryCode", "District", "Info"]).where("Name = 'Beijing'")
------ ----------- ------------- ---------- -----------------------------
| ID | Name | CountryCode | District | Info |
------ ----------- ------------- ---------- -----------------------------
| 1891 | Beijing | CHN | Peking | {"Population": 7472000} |
------ ----------- ------------- ---------- -----------------------------
1 row in set (0.00 sec)
相关信息
- 查看 TableUpdateFunction 获取完整的语法定义。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-table-delete.html
22.3.4.4 删除表
您可以使用 delete()
方法从数据库中的表中删除一些或所有记录。X DevAPI 提供了额外的方法与 delete()
方法一起使用,以过滤和排序要删除的记录。
使用条件删除记录
以下示例向 delete()
方法传递搜索条件。与条件匹配的所有记录都将从 city 表中删除。在此示例中,有一条记录符合条件。
mysql-js> db.city.delete().where("Name = 'Olympia'")
删除第一条记录
要删除 city 表中的第一条记录,请使用值为 1 的 limit()
方法。
mysql-js> db.city.delete().limit(1)
删除表中的所有记录
您可以删除表中的所有记录。要这样做,请使用不指定搜索条件的 delete()
方法。
注意
在不指定搜索条件的情况下删除记录时要小心;这样做会删除表中的所有记录。
删除表
dropCollection()
方法也可用于 MySQL Shell 中从数据库中删除关系表。例如,要从 world_x
数据库中删除 citytest
表,执行以下命令:
mysql-js> session.dropCollection("world_x", "citytest")
相关信息
- 参见 TableDeleteFunction 以获取完整的语法定义。
- 参见 第 22.3.2 节,“下载和导入 world_x 数据库”,了解重新创建
world_x
数据库的说明。
22.3.5 表中的文档
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-javascript-documents-in-tables.html
在 MySQL 中,表可以包含传统的关系数据、JSON 值或两者兼有。您可以通过将文档存储在具有本机JSON
数据类型的列中,将传统数据与 JSON 文档结合起来。
本节示例使用world_x
模式中的 city 表。
city 表描述
city 表有五列(或字段)。
代码语言:javascript复制 --------------- ------------ ------- ------- --------- ------------------
| Field | Type | Null | Key | Default | Extra |
--------------- ------------ ------- ------- --------- ------------------
| ID | int(11) | NO | PRI | null | auto_increment |
| Name | char(35) | NO | | | |
| CountryCode | char(3) | NO | | | |
| District | char(20) | NO | | | |
| Info | json | YES | | null | |
--------------- ------------ ------- ------- --------- ------------------
插入一条记录
要将文档插入到表的列中,请按正确顺序向values()
方法传递一个格式良好的 JSON 文档。在下面的示例中,一个文档作为最终值传递到 Info 列中以进行插入。
mysql-js> db.city.insert().values(
None, "San Francisco", "USA", "California", '{"Population":830000}')
选择一条记录
您可以发出带有评估表达式中文档值的搜索条件的查询。
代码语言:javascript复制mysql-js> db.city.select(["ID", "Name", "CountryCode", "District", "Info"]).where(
"CountryCode = :country and Info->'$.Population' > 1000000").bind(
'country', 'USA')
------ ---------------- ------------- ---------------- -----------------------------
| ID | Name | CountryCode | District | Info |
------ ---------------- ------------- ---------------- -----------------------------
| 3793 | New York | USA | New York | {"Population": 8008278} |
| 3794 | Los Angeles | USA | California | {"Population": 3694820} |
| 3795 | Chicago | USA | Illinois | {"Population": 2896016} |
| 3796 | Houston | USA | Texas | {"Population": 1953631} |
| 3797 | Philadelphia | USA | Pennsylvania | {"Population": 1517550} |
| 3798 | Phoenix | USA | Arizona | {"Population": 1321045} |
| 3799 | San Diego | USA | California | {"Population": 1223400} |
| 3800 | Dallas | USA | Texas | {"Population": 1188580} |
| 3801 | San Antonio | USA | Texas | {"Population": 1144646} |
------ ---------------- ------------- ---------------- -----------------------------
9 rows in set (0.01 sec)
相关信息
- 有关更多信息,请参阅与关系表和文档一起工作。
- 有关数据类型的详细描述,请参阅第 13.5 节,“JSON 数据类型”。
22.4 Python 快速入门指南:MySQL Shell 用于文档存储
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-python.html
22.4.1 MySQL Shell
22.4.2 下载和导入 world_x 数据库
22.4.3 文档和集合
22.4.4 关系表
22.4.5 表中的文档
本快速入门指南提供了使用 MySQL Shell 与文档存储应用程序进行交互原型设计的说明。该指南包括以下主题:
- MySQL 功能、MySQL Shell 和
world_x
示例模式的简介。 - 管理集合和文档的操作。
- 管理关系表的操作。
- 适用于表中文档的操作。
要按照这个快速入门指南,您需要安装了 X 插件的 MySQL 服务器,默认情况下在 8.0 版本中,以及用作客户端的 MySQL Shell。MySQL Shell 包括 X DevAPI,它在 JavaScript 和 Python 中都有实现,使您能够使用 X 协议连接到 MySQL 服务器实例,并将服务器用作文档存储。
相关信息
- MySQL Shell 8.0 提供了有关 MySQL Shell 的更深入信息。
- 有关本快速入门指南中使用的工具的更多信息,请参阅安装 MySQL Shell 和第 22.5 节,“X 插件”。
- 有关 MySQL Shell 支持的语言的更多信息,请参阅支持的语言。
- X DevAPI 用户指南提供了更多使用 X DevAPI 开发使用 MySQL 作为文档存储的应用程序的示例。
- 还提供了一个 JavaScript 快速入门指南。
22.4.1 MySQL Shell
译文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-python-shell.html
本快速入门指南假定您对 MySQL Shell 有一定的熟悉度。以下部分是一个高级概述,请参阅 MySQL Shell 文档以获取更多信息。MySQL Shell 是到 MySQL 服务器的统一脚本接口。它支持 JavaScript 和 Python 脚本。JavaScript 是默认处理模式。
启动 MySQL Shell
安装并启动 MySQL 服务器后,将 MySQL Shell 连接到服务器实例。您需要知道要连接的 MySQL 服务器实例的地址。为了能够将实例用作文档存储,服务器实例必须安装 X 插件,并且您应该使用 X 协议连接到服务器。例如,要连接到默认 X 协议端口 33060 上的实例 ds1.example.com
,请使用网络字符串 *
user*@ds1.example.com:33060
。
提示
如果您使用经典的 MySQL 协议连接到实例,例如使用默认的port
3306 而不是mysqlx_port
,则无法使用本教程中显示的文档存储功能。例如,db
全局对象未填充。要使用文档存储,始终使用 X 协议连接。
如果 MySQL Shell 尚未运行,请打开终端窗口并输入:
代码语言:javascript复制mysqlsh *user*@ds1.example.com:33060/world_x
或者,如果 MySQL Shell 已经在运行,请使用connect
命令:
connect *user*@ds1.example.com:33060/world_x
您需要指定要连接到的 MySQL 服务器实例的地址。例如,在上一个示例中:
- *
user
*代表您的 MySQL 帐户的用户名。 -
ds1.example.com
是运行 MySQL 的服务器实例的主机名。请将其替换为您正在使用作为文档存储的 MySQL 服务器实例的主机名。 - 本会话的默认模式为
world_x
。有关设置world_x
模式的说明,请参见第 22.4.2 节,“下载和导入 world_x 数据库”。
有关更多信息,请参见第 6.2.5 节,“使用类似 URI 字符串或键值对连接到服务器”。
当 MySQL Shell 打开时,mysql-js>
提示表示此会话的活动语言为 JavaScript。要将 MySQL Shell 切换到 Python 模式,请使用py
命令。
mysql-js> py
Switching to Python mode...
mysql-py>
MySQL Shell 支持输入行编辑如下:
- 左箭头和右箭头键在当前输入行内水平移动。
- 上箭头和下箭头键在先前输入的行集中上下移动。
- Backspace删除光标前的字符,并输入新字符以在光标位置输入它们。
- Enter将当前输入行发送到服务器。
获取 MySQL Shell 帮助
在命令解释器提示符处键入mysqlsh --help以获取命令行选项列表。
代码语言:javascript复制mysqlsh --help
在 MySQL Shell 提示符处键入help
以获取可用命令及其描述的列表。
mysql-py> help
在命令后键入help
,可获取有关单个 MySQL Shell 命令的详细帮助。例如,要查看connect
命令的帮助,请执行以下操作:
mysql-py> help connect
退出 MySQL Shell
要退出 MySQL Shell,请执行以下命令:
代码语言:javascript复制mysql-py> quit
相关信息
- 查看交互式代码执行以了解 MySQL Shell 中交互式代码执行的工作原理。
- 查看使用 MySQL Shell 入门以了解会话和连接选项。
22.4.2 下载并导入 world_x 数据库
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-python-download.html
作为快速入门指南的一部分,提供了一个示例模式,称为world_x
模式。许多示例演示了使用此模式的文档存储功能。启动您的 MySQL 服务器以加载world_x
模式,然后按照以下步骤操作:
下载world_x-db.zip。
将安装归档文件提取到临时位置,如/tmp/
。解压缩归档文件会生成一个名为world_x.sql
的单个文件。
将world_x.sql
文件导入到您的服务器。您可以选择:
在 SQL 模式下启动 MySQL Shell,并通过以下方式导入文件:
代码语言:javascript复制mysqlsh -u root --sql --file /tmp/world_x-db/world_x.sql
Enter password: ****
在运行时将 MySQL Shell 设置为 SQL 模式,并通过以下方式源化模式文件:
代码语言:javascript复制sql
Switching to SQL mode... Commands end with ;
source /tmp/world_x-db/world_x.sql
将/tmp/
替换为您系统上world_x.sql
文件的路径。如果提示,请输入密码。只要账户有权限创建新模式,非 root 账户也可以使用。
world_x 模式
world_x
示例模式包含以下 JSON 集合和关系表:
- 集合
countryinfo
:世界各国的信息。
- 表
-
country
:世界各国的最少信息。 -
city
:这些国家中一些城市的信息。 -
countrylanguage
:每个国家使用的语言。
-
相关信息
- MySQL Shell 会话解释了会话类型。
22.4.3 文档和集合
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-python-documents-collections.html
22.4.3.1 创建、列出和删除集合
22.4.3.2 使用集合
22.4.3.3 查找文档
22.4.3.4 修改文档
22.4.3.5 删除文档
22.4.3.6 创建和删除索引
当您将 MySQL 用作文档存储时,集合是您可以创建、列出和删除的模式内的容器。集合包含您可以添加、查找、更新和删除的 JSON 文档。
本节示例使用world_x
模式中的countryinfo
集合。有关设置world_x
模式的说明,请参见第 22.4.2 节,“下载和导入 world_x 数据库”。
文档
在 MySQL 中,文档被表示为 JSON 对象。在内部,它们以一种高效的二进制格式存储,可以实现快速查找和更新。
Python 的简单文档格式:
代码语言:javascript复制{"field1": "value", "field2" : 10, "field 3": null}
一组文档由一组由逗号分隔并包含在[
和]
字符中的文档组成。
Python 的简单文档数组:
代码语言:javascript复制[{"Name": "Aruba", "Code:": "ABW"}, {"Name": "Angola", "Code:": "AGO"}]
MySQL 支持 JSON 文档中以下 Python 值类型:
- 数字(整数和浮点数)
- 字符串
- 布尔值(False 和 True)
- 无
- 更多 JSON 值的数组
- 更多 JSON 值的嵌套(或嵌入)对象
集合
集合是共享目的并可能共享一个或多个索引的文档的容器。每个集合都有一个唯一的名称,并存在于单个模式中。
术语模式等同于数据库,意味着一组数据库对象,而不是用于强制数据结构和约束的关系模式。模式不会对集合中的文档强制一致性。
在这个快速入门指南中:
- 基本对象包括:
对象形式描述
dbdb
是分配给当前活动模式的全局变量。当您想对模式运行操作时,例如检索集合,您可以使用db
变量可用的方法。db.get_collections()
db.get_collections() 返回模式中集合的列表。使用列表获取对集合对象的引用,对其进行迭代等。 - 由集合范围内的基本操作包括:
操作形式描述
db.*
name*.add()
add() 方法将一个或多个文档插入到指定集合中。db.*
name*.find()
find() 方法返回指定集合中的一些或所有文档。db.*
name*.modify()
modify() 方法更新指定集合中的文档。db.*
name*.remove()
remove() 方法从指定集合中删除一个或多个文档。
相关信息
- 查看操作集合以获取一般概述。
- CRUD EBNF 定义 提供了操作的完整列表。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-python-collections-operations.html
22.4.3.1 创建、列出和删除集合
在 MySQL Shell 中,您可以创建新集合,在模式中获取现有集合的列表,并从模式中删除现有集合。集合名称区分大小写,每个集合名称必须是唯一的。
确认模式
要显示分配给模式变量的值,请执行:
代码语言:javascript复制mysql-py> db
如果模式值不是Schema:world_x
,则通过执行以下命令设置db
变量:
mysql-py> use world_x
创建一个集合
要在现有模式中创建新集合,请使用db
对象的createCollection()
方法。以下示例在world_x
模式中创建一个名为flags
的集合。
mysql-py> db.create_collection("flags")
该方法返回一个集合对象。
代码语言:javascript复制<Collection:flags>
列出集合
要显示world_x
模式中的所有集合,请使用db
对象的get_collections()
方法。当前连接到的服务器返回的集合将显示在括号之间。
mysql-py> db.get_collections()
[
<Collection:countryinfo>,
<Collection:flags>
]
删除一个集合
要从模式中删除现有集合,请使用db
对象的drop_collection()
方法。例如,要从当前模式中删除flags
集合,请执行:
mysql-py> db.drop_collection("flags")
drop_collection()
方法也可用于在 MySQL Shell 中从模式中删除关系表。
相关信息
- 查看集合对象以获取更多示例。
原文:
dev.mysql.com/doc/refman/8.0/en/mysql-shell-tutorial-python-documents-add.html
22.4.3.2 处理集合
要处理模式中的集合,请使用db
全局对象访问当前模式。在此示例中,我们使用之前导入的world_x
模式和countryinfo
集合。因此,您发出的操作的格式是db.*
collection_name*.operation
,其中*collection_name
*是执行操作的集合的名称。在以下示例中,操作是针对countryinfo
集合执行的。
添加文档
使用add()
方法将一个文档或文档列表插入到现有集合中。将以下文档插入到countryinfo
集合中。由于这是多行内容,请按两次Enter键以插入文档。
mysql-py> db.countryinfo.add(
{
"GNP": .6,
"IndepYear": 1967,
"Name": "Sealand",
"Code:": "SEA",
"demographics": {
"LifeExpectancy": 79,
"Population": 27
},
"geography": {
"Continent": "Europe",
"Region": "British Islands",
"SurfaceArea": 193
},
"government": {
"GovernmentForm": "Monarchy",
"HeadOfState": "Michael Bates"
}
}
)
该方法返回操作的状态。您可以通过搜索文档来验证操作。例如:
代码语言:javascript复制mysql-py> db.countryinfo.find("Name = 'Sealand'")
{
"GNP": 0.6,
"_id": "00005e2ff4af00000000000000f4",
"Name": "Sealand",
"Code:": "SEA",
"IndepYear": 1967,
"geography": {
"Region": "British Islands",
"Continent": "Europe",
"SurfaceArea": 193
},
"government": {
"HeadOfState": "Michael Bates",
"GovernmentForm": "Monarchy"
},
"demographics": {
"Population": 27,
"LifeExpectancy": 79
}
}
请注意,除了在添加文档时指定的字段之外,还有一个字段,即_id
。每个文档都需要一个名为_id
的标识符字段。_id
字段的值在同一集合中的所有文档中必须是唯一的。在 MySQL 8.0.11 及更高版本中,文档 ID 是由服务器生成的,而不是客户端,因此 MySQL Shell 不会自动设置_id
值。如果文档不包含_id
字段,MySQL 8.0.11 或更高版本的服务器会设置_id
值。在较早的 8.0 版本或 5.7 版本的 MySQL 服务器中,在这种情况下不会设置_id
值,因此您必须明确指定。如果不指定,MySQL Shell 将返回错误 5115 文档缺少必需字段。更多信息请参见理解文档 ID。
相关信息
- 请查看 CollectionAddFunction 以获取完整的语法定义。
- 请查看理解文档 ID。