二维码

使用JavaScript将数据从MongoDB导入MySQL

1961 人阅读 | 时间:2018年12月03日 17:16

MySQL Shell 8.0.13(GA)引入了一个新功能,可以轻松地将JSON文档导入MySQL。这篇新功能的基础知识在之前的博客文章中有所描述在这里,我们提供了有关此功能的更多详细信息,重点关注一些读者可能感兴趣的实际用例:如何将MongoDB中的JSON数据导入MySQL。可以应用相同的“配方”将数据从其他文档存储数据库导入MySQL,只要它们能够生成或导出数据到JSON即可。

迁移到不同数据库产品的任务,无论出于什么原因,都不应该掉以轻心,并且在许多情况下可以进行详细阐述。在其他方面,它取决于数据库服务器的数量及其在系统中的组织(单一服务器Vs复杂复制拓扑),数据大小,执行此任务的要求和可用资源。应定义全面详细的计划以成功执行此任务,包括执行所有必需步骤和相应的操作/工具。

注意:在开始迁移生产数据库系统之前,强烈建议您首先迁移数据样本并测试最终结果,以确保它符合您的期望和要求。这也可以让您测试迁移计划。

每个迁移计划都是不同的,并且特定于每个用例,但都可能包括常见步骤,例如更新应用程序以使用新数据库,以及导出和导入数据库数据。MySQL Shell中用于导入JSON数据的新功能有助于我们以更简单的方式执行此步骤。让我们看看它在实践中如何使用JavaScript将数据从MongoDB导入MySQL。

将数据从MongoDB导出到JSON

MongoDB允许您将所有数据导出到JSON,但它生成MongoDB Extended JSON的严格模式表示幸运的是,MySQL Shell JSON导入功能允许您转换BSON ObjectId类型,为此目的使用选项' convertBsonOid '。

注意:如果您的数据包含除ObjectId之外的其他BSON类型,它们以严格模式表示(例如,BinData,Date,Timestamp,NumberLong,NumberDecimal等),那么您可能需要手动处理这些类型的转换以进行转换根据您的要求正确使用它们(例如,在导入/导出过程中使用您自己的自定义转换脚本,或在应用程序级别转换它们)。有关BJSON类型及其在严格模式下的表示的更多信息,请参阅:BSON数据类型和关联表示

您需要做的第一件事实际上是将所有MongoDB数据导出到JSON文档。例如,假设您在“ 测试 ”数据库中有两个集合,名称为:restaurants和neighboors。您可以使用以下说明将MongoDB数据导出到JSON文档(每个集合一个文件):

1
2
3
4
5
6
7
$ mongoexport --db test --collection restaurants --out restaurants_mongo.json
2018-10-08T18:38:19.104+0100 connected to: localhost
2018-10-08T18:38:19.633+0100 exported 25359 records
$ mongoexport --db test --collection neighborhoods --out neighborhoods_mongo.json
2018-10-08T18:38:45.923+0100 connected to: localhost
2018-10-08T18:38:46.382+0100 exported 195 records

因此,您将获得两个带有数据的JSON文件“restaurants_mongo.json”和“neighborhoods_mongo.json”。

使用JavaScript将JSON数据导入MySQL

接下来,您只需使用新的MySQL Shell功能将生成的JSON文件导入MySQL数据库。为此,我们将在下一个示例中使用JavaScript函数“ util.importJson ”。但是,使用命令行可以实现同样的效果,如我们之前的博文所示

使用JavaScript将数据从MongoDB导入MySQL

命令:
util.importJson("/path_to_file/neighborhoods_mongo.json", {schema: "test", collection: "neighborhoods", convertBsonOid: true});
>util.importJson("/path_to_file/restaurants_mongo.json", {schema: "test", table: "restaurants", convertBsonOid: true});

可以看到,选项' convertBsonOid '与值“true”一起使用以导入两个文件。这会将MongoDB对象ID(OID)转换为正确的值。特别是,在将JSON数据导入集合的情况下,这是必需的,因为OID被转换为MySQL用于标识每个存储文档的集合Id(更具体地,' _ id '列和' _id '字段用于集合中的每个文档),否则在尝试将包含OID的字段导入集合中的MySQL文档Id(' _ id ')时将发出错误

使用JavaScript函数util.importJson()将第一个文件“neighborhoods_mongo.json”导入集合“ neighborhoods ” 使用相同的功能将第二个文件“restaurants_mongo.json”导入到表' restaurants '中。在这两种情况下,目标集合和表都不存在,并且使用JSON导入功能自动添加。

有关JSON导入实用程序的更多详细信息,请参见此处您也可以直接从MySQL Shell使用帮助,轻松获取有关该函数的其他信息,只需输入:“ \ h importJson ”。

将JSON导入集合和表之间的区别

使用不同的目标对象(集合与表)在导入结果中存在一些细微差别。让我们看一下结果数据的结构,以突出这些差异。

使用JavaScript将数据从MongoDB导入MySQL

命令:
\use test
db.getCollections(); 
session.sql("SHOW TABLES"); 
session.sql("SHOW CREATE TABLE test.neighborhoods"); 
>session.sql("SHOW CREATE TABLE test.restaurants");

首先,正如预期的那样,我们可以观察到' 餐馆 '数据未被列为集合,因为它是专门导入到表中的。但是,所有导入的文件都列为表,甚至是导入到集合的JSON文档。这是因为集合也在内部存储为MySQL中的表,但具有非常特定的结构。

查看“邻域”和“餐馆”表的“SHOW CREATE TABLE”语句的结果,可以观察它们之间的差异。在这两种情况下,JSON文档实际上都存储在JSON类型的“ doc ”列中区别在于识别栏。对于集合“ 邻域 ”,标识由“ _id ”列保存,该列与JSON文档中的“ _id ”字段匹配,该字段包含导入期间转换的OID的值。因此,OID实际上将匹配MySQL中每个导入的JSON文档的Id,用作主键。在表' 餐馆 ' 的情况下,标识由''持有'id '列是一个自动增量整数,表示为每个JSON文档(行)生成一个新标识。因此,原始OID将以某种方式被忽略,即不用作主键,尽管每个JSON文档中_id字段将包含从导入转换的OID值。

实际上,这种差异会影响您使用导入数据的方式。如果您选择一个集合作为导入的目标,您将能够利用所有MySQL文档存储功能(NoSQL + SQL)。另一方面,如果您选择一个表作为导入的目标,您将“限制”为可用的JSON类型功能和MySQL本机提供的JSON函数来操作您的JSON数据(仅限SQL)。

注意: MongoDB与MySQL文档存储的命令之间存在一些相关的语法差异,这可能有助于了解何时更新应用程序以使用MySQL。您可以在以下博文中找到有关它的更多信息:第一部分第二部分第三部分

如何为某些导入的数据创建新列

从前面的示例中,我们可以观察到所有导入的数据都存储在JSON类型的单个列中  但是,在某些情况下,可能需要将此数据的一部分放在另一列中,例如,在其上创建索引以改善某些查询的执行时间。让我们看一个简单快速的例子。假设我们将一些额外的JSON数据从“primer-dataset.json”导入到新的'my_restaurants'表中,并且我们的应用程序需要查询所有餐馆的名称以获取特定类型的菜肴。

使用JavaScript将数据从MongoDB导入MySQL
命令:
util.importJson("/path_to_file/primer-dataset.json", {schema: "test", table: "my_restaurants"}); 
shell.options.outputFormat = "vertical"; 
>session.sql('EXPLAIN SELECT doc->>"$.name" AS name FROM test.my_restaurants WHERE doc->>"$.cuisine" = "Italian"');

正如您所看到的,使用EXPLAIN语句显示有关查询执行计划的信息,我们可以验证查询是否将执行全表扫描以检索所需信息,这是不推荐的(特别是对于包含大量数据的表) 。幸运的是,通过为我们要用于过滤结果的属性添加新列和索引,可以使用ALTER TABLE语句在生成的列上创建二级索引,从而轻松解决此问题

使用JavaScript将数据从MongoDB导入MySQL
命令:
session.sql('ALTER TABLE test.my_restaurants ADD COLUMN cuisine VARCHAR(80) GENERATED ALWAYS AS (doc->>"$.cuisine") VIRTUAL, WITH VALIDATION'); 
session.sql('ALTER TABLE test.my_restaurants ADD INDEX cuisine_idx (cuisine)'); 
>session.sql('EXPLAIN SELECT doc->>"$.name" AS name FROM test.my_restaurants WHERE cuisine = "Italian"');

第一个ALTER TABLE语句将新列'cuisine'添加到'my_restaurants'表中,从每行的JSON数据的'cuisine'属性(在'doc'列中)中提取该列的值。在此特定情况下,创建了一个虚拟列并执行了验证以确保生成的值不在范围之外,但是其他选项可用于创建新列,有关详细信息,请参阅:ALTER TABLE和Generated Columns然后,执行第二个ALTER TABLE以在新的“cuisine”列上添加索引。

现在,分析EXPLAIN的结果,我们可以验证查询执行成本是否低得多,因为使用了索引(没有全表扫描)。

注意:在上图中,我们显示了从MySQL Workbench获得的查询执行计划图,以便更好地直观地说明每种情况的成本。

立即尝试并将您的反馈发送给我们

MySQL Shell可从以下链接下载。

可以在此处找到MySQL Shell的文档:https//dev.mysql.com/doc/mysql-shell/8.0/en/

以上示例中使用的示例JSON数据可通过以下链接公开获取。您可以下载并亲自试用。


©著作权归作者所有:来自ZhiKuGroup博客作者没文化的原创作品,如需转载,请注明出处,否则将追究法律责任 来源:ZhiKuGroup博客,欢迎分享。

评论专区
  • 昵 称必填
  • 邮 箱选填
  • 网 址选填
◎已有 0 人评论
搜索
作者介绍
30天热门
×
×
本站会员尊享VIP特权,现在就加入我们吧!登录注册×
»
会员登录
新用户注册
×
会员注册
已有账号登录
×