Help us understand the problem. What is going on with this article?

Drupal8 Migrate API 事始め

More than 3 years have passed since last update.

D8_Migrate_API.png

この記事は Drupal Advent Calendar 2016 の14日目の記事です。

D8 サイトに Migrate API を使ったコンテンツのインポート機能を実装した時に調べたことなどを紹介。


Drupal8 はマイグレーションのためのモジュール、Migrate モジュール (migrate) がコアに同梱されている。

Migrate モジュールが提供する Migrate API (と、拡張モジュール) を使うことで、例えば以下のようなことが可能になる。

  • D6、D7 のコンテンツを D8 に移行
  • CSV のコンテンツを D8 にインポート
  • プラグインを実装して独自形式のコンテンツを D8 にインポート

など

Migrate モジュールは API を提供するのみで、実際にマイグレーションを行うためには用途に合わせて他のモジュールを組み合わせる必要がある。

Migrate API でマイグレーションを行うまでの流れ

  1. Migrate モジュールを有効化
  2. 最低限必要な contributed モジュールをインストール
  3. マイグレーションの内容に合わせて必要なモジュールを選んでインストール
  4. マイグレーション構成 (configuration) を YAML で作ってインポート
  5. drush migrate-import コマンドでマイグレーション実行

各モジュールの概要

Migrate (migrate)

  • コアモジュール (まだ Experimental でデフォルトでは無効状態)
  • Migrate API -- マイグレーション機能の基盤 を提供
    • プラグイン機構 + 基本的なプラグイン
    • マイグレーションの進捗管理
    • 元データと対応する D8 エンティティの対応付け
    • などなど
  • 管理画面の UI、drush コマンドなどは無い
  • マイグレーションを実行するには他のモジュールが必要

Migrate Plus (migrate_plus)

  • いろいろ追加機能が含まれる (よくわかってない)
  • configuration、source プラグインなどのサンプルもある
  • Migrate Tools を使うのに必要

Migrate Tools (migrate_tools)

  • マイグレーションを実行できる drush コマンドを提供
    • $ drush mi (migrate-import: インポート実行)
    • $ drush ms (migrate-status: ステータス確認)
    • その他ロールバック、エラーメッセージの確認コマンドなど
  • 管理画面からマイグレーションを一覧、管理できる
    • ただし管理画面では実行は行えないので drush コマンドを使う

Migrate API の仕組みとプラグイン

必要なプラグイン (を提供しているモジュール) を選んで configuration を作るためには、Migrate API によるマイグレーションの仕組みを理解する必要がある。

マイグレーションは以下の3種類のプラグインを組み合わせて行う。

  • Migrate source
  • Migrate process
  • Migrate destination

これらの組み合わせとデータの流れを表したのが冒頭にも貼ったこちらの図。

D8_Migrate_API.png

以下のような流れで、読み込まれた元データが D8 のエンティティとして保存される。

  1. source plugin が元データを読み込み
    • source はマイグレーションに1つのみ存在
    • 元データの形式に対応したプラグインを選ぶ
  2. process plugin が読み込まれたデータを変換、destination のフィールドにマッピング
    • process は複数使う
    • ひとつのフィールドの値を複数の process plugin で順に変換することもできる
    • ただの固定値を destination に渡す事も可
  3. destination plugin がマッピングされたデータを D8 エンティティとして保存
    • destination も source と同じく1つだけ使用
    • 保存したい形式に対応したプラグインを選ぶ

このように3種類のプラグインを組み合わせることで、要求に応じた柔軟なマイグレーションができるようになっている。

CSV インポートチュートリアル

Drupal.org に Migrate Source CSV プラグインを使って CSV を D8 の article にインポートするチュートリアルがある。

Using the Migrate Source CSV plugin | Drupal.org

CSV は以下のようなもの。

acme_articles.csv
Id2,title,body 
1,title 1,some body text 1 
2,title 2,some body text 2 
3,title 3,some body text 3

これをインポートするマイグレーションの YAML。

migrate_plus.migration.basics.yml
id: basics
label: Import articles
migration_groups:
  - ACME import

source:
  plugin: csv
  path: '/path/to/file/acme_articles.csv'
  header_row_count: 1
  keys:
    - Id2

process:
  title: title
  body: body
  type:
    plugin: default_value
    default_value: article

destination:
  plugin: entity:node

実行方法

1. モジュールをインストール

  • Migrate
  • Migrate Plus
  • Migrate Tools
  • Migrate Source CSV

2. YAML をインポート

上記の YAML をインポートする。

管理画面からインポートする場合は admin/config/development/configuration/single/import
構成タイプで Migration を選択し、YAML を貼り付けてインポートする。

config_devel をインストールすれば drush からもインポートできる。
YAML をいじりつつ試す場合は drush からインポートする方が簡単だと思う。

// ファイル名は migrate_plus.migration.<migration_id>.yml の形式になっている必要がある。
// YAML を変更して上書き保存する場合も同様のコマンド。
$ drush cdi1 path/to/migrate_plus.migration.basics.yml

YAML に問題がない場合は、以下の URL でインポートされる・された件数などを確認できる。
admin/structure/migrate/manage/misumi/migrations

進捗などのステータスは drush コマンドでも確認できる。

// migrate-status (ms)
$ drush ms
 Group: Default (default)  状態  Total  Imported  Unprocessed  Last imported
 basics                    Idle  3      0         3

3. 実行

drush migrate-import (mi) コマンドでマイグレーションを実行する。

$ drush mi basics
Processed 3 items (3 created, 0 updated, 0 failed, 0 ignored) - done with 'basics'

// エラーで取り込めないレコードがあった場合は migrate-messages (mmsg) コマンドでエラー内容を確認できる
$ drush mmsg basics

// CSV を修正して再インポートする時は --update を付けて migrate-import する。
// 既にインポート済みのレコードは追加されず、既存のエンティティが更新される。
$ drush mi --update basics

// ※ キーとなる値 (ここでは Id2 カラムの値) を変更すると別レコードと認識されるのでエンティティも新しく追加される。

YAML の各行の意味

id、label

id: basics
label: Import articles

このidを drush migrate-* の引数に指定する。

migration_gorups

migration_groups:
  - ACME import

グループを指定しておくと、グループのマイグレーションを一括で実行することもできる。

source

source:
  plugin: csv
  path: '/path/to/file/acme_articles.csv'
  header_row_count: 1
  keys:
    - Id2

使用する source plugin の指定とそのパラメータ。

keys で指定したカラムの値がその行のキーとして扱われ、インポートされたコンテンツの ID (この場合は article の nid) と紐付けられる。

初回インポート時は新しい article が作成されるが、2回目以降に実行するとマッピングされた既存の article が更新される。
更新時は --update を付けて drush mi --update <migration_id> を実行する。

process

process:
  title: title
  body: body
  type:
    plugin: default_value
    default_value: article

読み込まれたデータの変換と destination へのマッピング。

title: title の左側 (キー) が destination のフィールド名、右側が source のフィールド名になっている。
destination の title と body (つまり article の title、body プロパティ) には、CSV の同名のフィールドがそのまま保存される。

type フィールドは default_value プラグインを使って固定値 ("article") を設定している。

上記で使用している default_value の他にも十数種類のプラグインが存在している。
https://www.drupal.org/docs/8/api/migrate-api/migrate-process

process の形式は以下のパターンがある。

process:
  <destination_field_1>: <source_field>
  <destination_field_2>:
    - plugin: <process_plugin_id>
    - <parameter1>
    - <parameter2...>
  <destination_field_3>:
    -
      plugin: <process_plugin_1>
      <parameter>
    -
      plugin: <process_plugin_2>

ひとつのフィールドを複数の process で処理する場合は3つ目の形式で書く。

ちなみに1つ目の書き方は get plugin 用の省略形。

destination

destination:
  plugin: entity:node

process でマッピングされたデータを保存する destination plugin の指定。
node として保存したいので entity:node プラグインを使う。

最終的には、CSV の title、body カラム、固定値の type = "article" が node に保存される。
CSV の Id2 は 作成された node とのマッピングに使用されるだけで node のフィールドとしては保存されない。

参考資料

Drupal.org のドキュメントには目を通しておくべきだと思う。 (多いけど)
どのようなプラグインがあるのかを知るのと、プラグインの使い方も参考になる。

YAML の書き方、プラグインの作り方の参考資料

Migrate Plus の example モジュール (migrate_example、migrate_example_advanced) が参考になる。
source プラグインの実装も含まれている。

ちなみに、process で独自の変換処理を書きたくなった時は callback プラグインを使うとお手軽。
モジュールに関数を定義しておくだけで YAML から使えるようになる。

プラグインは役割が細かく分かれているおかげで、それぞれの実装はシンプルなものになっているので、既存のプラグインの実装を読むのが理解も早いと思う。

Migrate API 所感

今回 D8 サイトに実装したインポート機能は、元データが CSV (メタ情報) + 静的ファイル (body データ) に分離しているというちょっと特殊な形だったため、Migrate API でやるか、完全に独自のインポートモジュールを作成するかで迷ったが、あまり迷っている時間もなかったため Migrate API を使った。

結果的には良い選択だったと思う。

独自実装と比較すると、Migrate API には以下のようなメリットがあると思う。

  • プラグインが分離しているおかげで、どのような形式のデータにも対応できる
    • 今回は CSV と静的ファイルを読み込む source プラグインを作って対応した
  • 既存のプラグインと組み合わせられるので実装の手間が省ける
  • 元データとエンティティの紐付けを管理してくれる
    • 元データを編集して更新、などが簡単にできる (キーとなる値は適切に選ぶ必要がある)
  • 進捗を管理してくれる
  • (試してないが) インポートの取り消しもできるらしい
  • 覚えておくと色々応用が効きそう
    • 大抵の事は YAML を書くだけで実現できる
    • 自動テストでテストデータを入れるのにも使えそう
masam10
≧ω≦
dgcircus
オープンソースCMS「Drupal」の導入・カスタマイズ開発、スマートフォンアプリ開発を行うIT企業
https://www.dgcircus.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした