我尝试使用Embulk将MongoDB中的数据迁移到MySQL

本文是ZOZO Technologies Advent Calendar第2天的第24篇文章。

概述

ZOZOTOWN的替换工具采用Embulk进行数据库数据迁移。
Embulk是一种用于数据传输的工具,可以通过组合插件(输入、输出、过滤器)来自由传输各种数据。

这次我们进行了从MongoDB到MySQL的数据迁移,
由于相关信息比较少,希望能提供参考,我想介绍一下步骤。

太长了,不想读。

embulk-input-mongodb、embulk-output-mysql
を使う
filter を使いデータ加工を行う必要がある

カラム展開は expand_json を使う
NULLデータの default 値は column で設定

过渡的必要条件

我们根据以下要求进行了数据迁移。

    • MongoDB 2.6 → mysql 5.7 へデータ移行

 

    • MongoDB のデータはフィールド数がまちまち

 

    MySQLで NOT NULL としたいカラムに対し、MongoDB で Key が存在しないデータの場合デフォルト値を指定して移行

建立测试环境

为了能够轻松进行操作确认,我们可以使用docker-compose快速创建验证环境。
如果您只想确认流程,请忽略这里的内容。

version: "3.7"
networks:
  backend:
services:
  mongodb:
    image: mongo:2.6
    container_name: mongodb
    networks:
      - backend
    ports:
      - 27018:27017
  mysql:
    image: mysql:5.7
    container_name: mysql
    environment:
      - MYSQL_DATABASE=test
      - MYSQL_ROOT_PASSWORD=hogehoge
    networks:
      - backend
    ports:
      - 3307:3306

请在创建上述docker-compose.yml文件后执行以下命令。

$ docker-compose up -d
$ docker-compose exec mongodb mongo test
(mongo)> db.Users.insert([
{"id": 1, "name": "hoge", "email": "hoge@example.com", "age": 20},
{"id": 2, "name": "fuga", "email": "fuga@example.com", "age": 25},
{"id": 3, "name": "foo", "age": 30}
])

如果存储了下面这样的数据,准备工作就可以了。

> db.Users.find()
{ "_id" : ObjectId("5fe2679a62a2dec6c0f0751b"), "id" : 1, "name" : "hoge", "email" : "hoge@example.com", "age" : 20 }
{ "_id" : ObjectId("5fe2679a62a2dec6c0f0751c"), "id" : 2, "name" : "fuga", "email" : "fuga@example.com", "age" : 25 }
{ "_id" : ObjectId("5fe2679a62a2dec6c0f0751d"), "id" : 3, "name" : "foo", "age" : 30 }

将MongoDB中的数据迁移到MySQL

输入-MongoDB、输出-MySQL插件。

通过使用 `embulk-input-mongodb`,可以将数据从 MongoDB 迁移到 MySQL。

Embulk的YAML如下所示。

in:
  type: mongodb
  hosts:
  - {host: 127.0.0.1, port: 27018}
  database: test
  collection: "Users"
out:
  type: mysql
  host: 127.0.0.1
  port: 3307
  user: root
  password: hogehoge
  database: test
  table: users
  mode: replace

当执行embulk run config.yml时,可以将以下数据迁移到MySQL users表中。

$ mysql -u root -phogehoge -P 3307 -h 127.0.0.1 test -e "select * from users;"
+-------------------------------------------------------------------------------------------------+
| record                                                                                          |
+-------------------------------------------------------------------------------------------------+
| {"_id":"5fe2679a62a2dec6c0f0751b","id":1.0,"name":"hoge","email":"hoge@example.com","age":20.0} |
| {"_id":"5fe2679a62a2dec6c0f0751c","id":2.0,"name":"fuga","email":"fuga@example.com","age":25.0} |
| {"_id":"5fe2679a62a2dec6c0f0751d","id":3.0,"name":"foo","age":30.0}                             |
+-------------------------------------------------------------------------------------------------+

我已成功将 MongoDB 的数据迁移到 MySQL。
然而,记录列中的数据仍保持为 JSON 结构。
因此,我将使用过滤器对数据进行处理。

使用expand_json过滤器,将JSON展开到列中

使用过滤器:expand_json。

在 embulk-input-mongodb 中,默认输出的列名为 record,所以将 json_column_name 设置为 record。

in:
  type: mongodb
  hosts:
  - {host: 127.0.0.1, port: 27018}
  database: test
  collection: "Users"
filters:
  - type: expand_json
    json_column_name: record
    expanded_columns:
      - {name: id, type: long}
      - {name: name, type: string}
      - {name: email, type: string}
      - {name: age, type: long}
out:
  type: mysql
  host: 127.0.0.1
  port: 3307
  user: root
  password: hogehoge
  database: test
  table: users
  mode: replace

运行`embulk run config.yml`可以将以下数据迁移到MySQL的`users`表中。

$ mysql -u root -phogehoge -P 3307 -h 127.0.0.1 test -e "select * from users;"
+------+------+------------------+------+
| id   | name | email            | age  |
+------+------+------------------+------+
|    1 | hoge | hoge@example.com |   20 |
|    2 | fuga | fuga@example.com |   25 |
|    3 | foo  | NULL             |   30 |
+------+------+------------------+------+

json をカラムに展開しつつデータ移行できました。
MongoDB で email の Key を持たないデータは、email が NULL となっています。
email カラムを NOT NULL としたい場合この状態は望ましくありません。
こちらもフィルターを使うことで、NULLではなく ”(空) など default 値を設定することが出来ます。

使用列过滤器,指定默认值。

使用过滤器:列。

in:
  type: mongodb
  hosts:
  - {host: 127.0.0.1, port: 27018}
  database: test
  collection: "Users"
filters:
  - type: expand_json
    json_column_name: record
    expanded_columns:
      - {name: id, type: long}
      - {name: name, type: string}
      - {name: email, type: string}
      - {name: age, type: long}
  - type: column
    columns:
      - {name: id}
      - {name: name}
      - {name: email, default: ''}
      - {name: age}
out:
  type: mysql
  host: 127.0.0.1
  port: 3307
  user: root
  password: hogehoge
  database: test
  table: users
  mode: replace

执行”embulk run config.yml”命令可以将以下数据迁移到MySQL users表中。

+------+------+------------------+------+
| id   | name | email            | age  |
+------+------+------------------+------+
|    1 | hoge | hoge@example.com |   20 |
|    2 | fuga | fuga@example.com |   25 |
|    3 | foo  |                  |   30 |
+------+------+------------------+------+

以上是根据要求成功地进行了数据迁移,通过将电子邮件列设置为空”。

概述

使用 embulk-input-mongodb 获取数据,并结合过滤器,成功将 MongoDB 的数据迁移到 MySQL,按照要求完成了数据迁移。

由于 Embulk 内建了许多插件,可以灵活地满足各种需求,因此我们可以根据不同的要求进行适应。
(在我们公司中,Sonots、Civitaspo 等人发布了各种插件,本次使用的过滤器也是由他们开发的。)

如果您对涉及数据迁移的替换时机感兴趣的话,强烈建议您使用Embulk,轻松进行数据迁移的尝试。

感谢您阅读。

广告
将在 10 秒后关闭
bannerAds