[Keystone] 関係性の理解

関係性の理解

Keystone において、異なるコンテンツのリスト間で作成する接続を『関係性』と呼びます。構築するものは、必要に応じて大きく異なります。このガイドでは、構造化されたコンテンツを通じてプロジェクトに価値をもたらすために、Keystone における関係性を考え、構成する方法を説明します。

関係性について考える方法

Keystone は、関係性に関して柔軟性が高く、必要なものを取得するには、2 つの重要な質問に答える必要があります。

  • 関係性からデータにアクセスする必要がある側はどちらですか?
    あなたのニーズに応じて、関係性が1つの場合と2つの場合のどちらが必要かを定義します。
  • 関係性の各側に必要な接続はいくつですか?
    これを理解することで、構成する必要がある基数の種類が決まります。

これらのトピックは、例を通じて理解しやすくなります。私たちは、ブログ記事の投稿タイプと投稿者のユーザータイプを持つブログアプリの使用例を通じて、関係性の基本設定を探求します。

Keystone で関係性を定義する方法

関係性は、list() 内の relationship フィールドタイプを使用して作成されます。ブログの例では、relationship フィールドの ref 構成オプションを使用して、ブログ投稿をいくつかのユーザーに接続することができます。例えば、次のようになります。

import { config, list } from '@keystone-6/core';
import { text, relationship } from '@keystone-6/core/fields';

export default config({
  lists: {
    User: list({ fields: { name: text() } }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        authors: relationship({ ref: 'User', many: true, }),
      },
    }),
  },
});

片側と両側の関係性

Keystone では、接続する2つのリストの片側または両側から関係性を定義することができます。これらを片側と両側の関係性と呼びます。

片側

Post リストは、authors フィールドを介して User リストに関連付けられています。この種の関係性により、GraphQL API で投稿の著者をクエリできます。例えば、次のようになります。

query {
  posts {
    title
    content
    authors {
      name
    }
  }
}

両側

投稿のすべての著者を見つけることができれば、特定のユーザーが書いたすべての投稿も見つけることができます。これを行うには、スキーマで両側の関係性を構成する必要があります。

...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
        // relates posts to authors
        posts: relationship({ref: 'Post.authors', many: true }),
      },
    }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        // relates authors to posts
        authors: relationship({ ref: 'User.posts', many: true }),
      },
    }),
  },
});

上記の例では、Userリストにpostsフィールドを追加し、authorsフィールドのref設定をUser.postsに変更しました。

関係性が両側になったので、次のようにして各ユーザーが書いたすべての投稿をクエリできます。

query {
  users {
    name
    posts {
      title
      content
    }
  }
}

自己参照関係

Keystone では、同じリストを参照する片側および両側の関係性も定義できます。Twitter のフォロー関係のような片側の関係を作成するには、以下のようにします。

...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
        follows: relationship({ ref: 'User', many: true }),
      },
    }),
  },
});

また、これを両側の関係に変更して、すべてのユーザーのフォロワーにもアクセスできるようにすることもできます。

...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
        follows: relationship({ ref: 'User.followers', many: true }),
        followers: relationship({ ref: 'User.follows', many: true }),
      },
    }),
  },
});

基数の確立

基数は、関係性の各側に存在できるアイテムの数を表す用語です。各側は、1つまたは多数の関連アイテムを持つことができます。各関係に片側または両側があるため、以下のオプションが利用可能です。

関係タイプ 一対一 一対多 多対多
片側
両側

基数は、関係フィールドの many 構成オプションを介して定義されます。これは、真偽値であり、次のようになります。

  • false = one
  • true = many
    ブログのコンテキストで、それぞれの基数のタイプを設定する方法を見てみましょう。

一方向の基数

一対多
  • 投稿は1人の著者を持つことができます
  • ユーザーは複数の投稿を持つことができます
...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
      },
    }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        author: relationship({ ref: 'User', many: false }),
      },
    }),
  },
});
多対多
  • 投稿は複数の著者を持つことができます
  • ユーザーは複数の投稿を持つことができます
...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
      },
    }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        authors: relationship({ ref: 'User', many: true }),
      },
    }),
  },
});

双方向の基数

一対一
  • 投稿は単一の著者を持ちます
  • ユーザーは1つの投稿しか作成できません
...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
        post: relationship({ ref: 'Post.author', many: false }),
      },
    }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        author: relationship({ ref: 'User.post', many: false }),
      },
    }),
  },
});
一対多
  • 投稿は単一の著者を持ちます
  • ユーザーは複数の投稿を持つことができます
...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
        posts: relationship({ref: 'Post.author', many: true }),
      },
    }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        author: relationship({ ref: 'User.posts', many: false }),
      },
    }),
  },
});
多対多
  • 投稿は複数の著者を持つことができます
  • ユーザーは複数の投稿を持つことができます
...
export default config({
  lists: {
    User: list({
      fields: {
        name: text(),
        posts: relationship({ ref: 'Post.authors', many: true }),
      },
    }),
    Post: list({
      fields: {
        title: text(),
        content: text(),
        authors: relationship({ ref: 'User.posts', many: true }),
      },
    }),
  },
});

Summary

Keystone の関係は、リレーションシップフィールドタイプを使用して管理されます。ref構成オプションによって、それらを片側または両側に構成することができます。その多重度は、many フラグを使用して設定できます。Keystone は、必要に応じて達成したいことに基づいて選択できる柔軟性を提供します。