Contentful記事のquery-entriesに必要なキー構成をエクスポートデータから確認する

Contentfulの記事検索をCLIから行う際に、クエリ指定例が中々見つからず苦労しました。ターミナルからのtoken発行と、1件指定検索を元にキーを見つけるプロセスを記事としました。
2024.05.31

DevIO執筆環境の変更に伴うContentful操作を必要とする期日が迫り、Contentful の APIを経由しての投稿が手軽に出来ないものかとCLI等を触っていました。

Contentfulの設計を試すとわかりますが、Notionのブロック構成と相性よしとは言い難い仕組みです。少なくともNotionからエクスポートしたMarkdownフォーマットの原稿をターミナル経由でContentfulへ手軽には送れません。NotionからContentfulへのマイグレーションを有料で実施できるSaaSも検索すると出てくる程です。

WordPressと違って、過去の記事検索をクエリベースでやりやすいのはメリットと言えます。課題はクエリ実行までを手順立てて解説してあるページが見当たらないところでしょうか。

NotionからContentfulへの原稿転送は一旦見送り、過去記事の検索を行う目的でクエリの組み立て方について調べた結果を元に記事としました。

Contentful CLIの設定

ターミナル上で実施する際には必須と言えます。

ブラウザ上からContentfulにログインしてCMA Tokenを発行する方法もありますが、CLIをインストールした場合はCLI経由のログインでも可能です。contentful login を実行しましょう。ブラウザ経由で認証してtokenを取得、ターミナル上で送信します。

% npm install -g contentful-cli 
% contentful login                                                                                                     
A browser window will open where you will log in (or sign up if you don’t have an account), authorize this CLI tool and paste your CMA token here:
? Continue login on the browser? Yes
? Paste your token here: *************************************
Great! You've successfully logged in!
╭─────────────────────────────────────────────────────────────────────────╮
│                                                                         │
│   Your management token: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX    │
│   Stored at: /Users/user/.contentfulrc.json                             │
│                                                                         │
╰─────────────────────────────────────────────────────────────────────────╯
Have any feedback for the Contentful CLI? We'd love to hear from you! Check out our five question developer experience survey at:
  https://xxxxxxxxxxx.typeform.com/to/xxxxxx

APIの呼び出しにはSpaceIDが必要です。contentful space list を実行して確認します。

% contentful space list
┌──────────────┬──────────────┐
│ Space name   │ Space id     │
├──────────────┼──────────────┤
│ DevelopersIO │ xxxxxxxxxxxx │
└──────────────┴──────────────┘

API呼び出しに必要なmanagementTokenとspaceIdが揃いました。JSONファイルとして保存しておきます。

% vim api-config.json
{
  "spaceId": "xxxxxxxxxxxx",
  "managementToken": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "contentFile": "contentful-export.json"
}

APIを呼び出す

膨大なデータが既に登録されているContentfulスペースに対する呼び出しで忘れずすべきことはクエリの指定です。もしもクエリを指定しなかった場合、全件が一度にエクスポートされてしまいます。難点はAPI向けクエリのビルド用フォームやコンソールといったものがないところです。

エクスポートデータを元に構成を確認する場合は複数記事は必要ないため、Contentfulの記事一覧からいずれかの記事IDを取得して、クエリでsys.id.sys.idに特定IDを指定してのエクスポートを試みます。

contentful space export --export-dir contentful_export/ --query-entries 'sys.id.sys.id=xxxxxxxxxxxx' --config api-config.json

途中エラーが出る場合は必要に応じてskipフラグを追加します。

--skip-webhooks --skip-roles

正常に完了すると、ローカルにJSONフォーマットでダウンロードされます。

  ✔ Initialize client (1s)
  ✔ Fetching data from space
    ✔ Connecting to space (1s)
    ✔ Fetching content types data (1s)
    ✔ Fetching tags data (1s)
    ✔ Fetching editor interfaces data (4s)
    ✔ Fetching content entries data (1s)
    ✔ Fetching assets data (2s)
    ✔ Fetching locales data (1s)
    ↓ Fetching webhooks data [skipped]
    ↓ Fetching roles data [skipped]
  ↓ Download assets [skipped]
  ✔ Write export log file
    ✔ Lookup directory to store the logs
    ✔ Create log directory
    ✔ Writing data to file
┌──────────────────────────┐
│ Exported entities        │
├───────────────────┬──────┤
│ Content Types     │ 12   │
├───────────────────┼──────┤
│ Tags              │ 3    │
├───────────────────┼──────┤
│ Editor Interfaces │ 12   │
├───────────────────┼──────┤
│ Entries           │ 1    │
├───────────────────┼──────┤
│ Assets            │ 1034 │
├───────────────────┼──────┤
│ Locales           │ 1    │
└───────────────────┴──────┘
The export took less than a minute (7s)

Stored space data to json file at: /Users/user/path/to/contentful_export/contentful-export.json

The export was successful.
✨ Done

ダウンロードしたJSONファイルを見ると、contentTypes下を元に指定すべきキー構成も判ってきます。

% cat contentful_export/contentful-export.json | head -20                                                              [main][..625d23027241a]
{
  "contentTypes": [
    {
      "sys": {
        "space": {
          "sys": {
            "type": "Link",
            "linkType": "Space",
            "id": "xxxxxxxxxx"
          }
        },
        "id": "blogPost",
        "type": "ContentType",
        "createdAt": "2023-06-16T10:11:32.722Z",
        "updatedAt": "2024-05-29T08:50:25.536Z",
        "environment": {
          "sys": {
            "id": "master",
            "type": "Link",
            "linkType": "Environment"

一部のパラメータについては眉間にシワが寄るかもしれませんが、大体はクエリ作成時に役立つことでしょう。

あとがき

クエリ指定がTypeScriptのサンプルコードのみ掲載されていたりと、ターミナル上から指定する方法が中々見つからず難儀しました。

1件でも記事のデータがエクスポートできれば各コンテンツ指定に必要なキー構成も見えてくるので、クエリで分からない場合は先ずは特定記事のエクスポートから始めてみましょう。