🍀

【Shopify.dev和訳】API usage/Pagination/GraphQL

2021/09/09に公開約8,500字

この記事について

この記事は、API usage/Pagination の記事を和訳したものです。

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

GraphQL による結果のページング

接続を使ってリソースのリストを取得する際には、引数を使って取得する結果の数を指定します。カーソルベースのページネーションを使用すると、接続から取得する結果のセットを選択できます。

コネクションの概要

コネクションは、ノードのリストを取得します。ノードは、グローバル ID を持ち、Ordertype などのスキーマで定義された型を持つオブジェクトです。ノードはエッジによって接続されていると言われています。

例えば、orders 接続は、クエリルートと Order ノードをつなぐすべてのエッジを見つけ、要求されたデータを各ノードから返します。例えば、lineItems コネクションを使用して、orders コネクション内の各注文のラインアイテムを取得するように、他のコネクションの中にコネクションを入れ子にすることもできます。

注文のリストをページネーションするには、Order タイプには含まれていないデータを返す必要があります。このデータには、接続内にさらに多くの結果があるかどうか、どの注文が現在の結果に含まれているかなどが含まれます。ノードオブジェクトに含まれないフィールドを選択できるように、Shopify はすべての接続にedgesnodeレイヤーを含めています。

query {
  orders(first: 2) {
    edges {
      node {
        id
      }
    }
  }
}
{
  "data": {
    "orders": {
      "edges": [
        {
          "node": {
            "id": ...
          }
        },
        {
          "node": {
            "id": ...
          }
        }
      ]
    }
  }
}
  • edges - 接続の各エッジから取得するフィールドの選択に使用します。edges フィールドは、コネクション内の各エッジから選択されたフィールドを取得するため、for-loop に似ています。
  • node - 各エッジのノードから取得したいフィールドを選択するために使用します。
    コネクション、エッジ、ノードの各レベルでフィールドを指定すると、ページネーションに使用される pageInfocursor というフィールドを含めることができます。
query {
  orders(first: 10) {
    pageInfo {
      # 現在の検索結果のページに関する詳細を返します
      hasNextPage # このページの後にも結果があるかどうか
      hasPreviousPage # このページの前にも結果があるかどうかpage
    }
    edges {
      cursor # コネクション内のエッジの位置を示すマーカー
      node {
        name # 各ノードで返されるフィールド
      }
    }
  }
}

pageInfo フィールド

各接続は、2 つのフィールドを持つ PageInfo オブジェクトを返すことができます。

  • hasNextPage (Boolean!) - 現在のセグメントの後に、接続に結果があるかどうか。
  • hasPreviousPage (Boolean!) - 現在のセグメントの前に、接続内に結果があるかどうか。
    ページ情報は、各エッジではなく、クエリごとに一度だけ取得するので、接続レベルでは、edgesフィールドの横にpageInfoを含めます。

POST /admin/api/2021-07/graphql.json

query {
  products(first: 3) {
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    edges {
      node {
        id
      }
    }
  }
}

JSON response

Copy
{
  "data": {
    "products": {
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": false
      },
      "edges": [
        {
          "node": {
            "id": ...
          }
        },
        {
          "node": {
            "id": ...
          }
        },
        {
          "node": {
            "id": ...
          }
        }
      ]
    }
  },
  ...
}

https://shopify-graphiql-app.shopifycloud.com/login?return_to=%2F%3Fquery%3Dquery%2509%2528%2524numProducts%253A%2509Int%2521%252C%2509%2524cursor%253A%2509String%2529%257B%250A%2509%2509products%2528first%253A%2509%2524numProducts%252C%2509after%253A%2509%2524cursor%2529%2509%257B%250A%2509%2509%2509%2509pageInfo%2509%257B%250A%2509%2509%2509%2509%2509%2509hasNextPage%250A%2509%2509%2509%2509%2509%2509hasPreviousPage%250A%2509%2509%2509%2509%257D%250A%2509%2509%2509%2509edges%2509%257B%250A%2509%2509%2509%2509%2509%2509cursor%250A%2509%2509%2509%2509%2509%2509node%2509%257B%250A%2509%2509%2509%2509%2509%2509%2509%2509title%250A%2509%2509%2509%2509%2509%2509%257D%250A%2509%2509%2509%2509%257D%250A%2509%2509%257D%250A%257D%26variables%3D%257B%250A%2509%2509%2522numProducts%2522%253A%25093%250A%257D

カーソルフィールド

コネクション内の各エッジは、コネクション内のエッジの位置への参照であるカーソルを返すことができる。カーソルはnodeではなくエッジのプロパティであるため、エッジレベルではノードフィールドの横にcursorフィールドを含める。

query {
  orders(first: 10) {
    edges {
      cursor
      node {
        id
      }
    }
  }
}

エッジのカーソルを出発点にして、接続中の前後のノードを取り出すことができます。

カーソルベースのページネーション

クエリに pageInfo フィールドと cursor フィールドを含めることで、結果をページネーションすることができます。以下の例では、両方のフィールドを含み、クエリ変数を使用してその値を引数として渡しています。$orderNum 変数は必須であり、返す結果の数を指定するために使用します。$cursor 変数は必須ではありません。$cursor変数がない場合、afterの引数は無視されます。

POST /admin/api/2021-07/graphql.json

query ($numProducts: Int!, $cursor: String) {
  products(first: $numProducts, after: $cursor) {
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    edges {
      cursor
      node {
        title
      }
    }
  }
}

変数

{
  "numProducts": 3
}

JSON レスポンス

{
  "data": {
    "products": {
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": false
      },
      "edges": [
        {
          "cursor": "eyJsYXN0X2lkIjoxMDA3OTc4ODg3NiwibGFzdF92YWx1ZSI6IjEwMDc5Nzg4ODc2In0=",
          "node": {
            "title": "The T-Shirt"
          }
        },
        {
          "cursor": "eyJsYXN0X2lkIjoxMDA3OTc5MzQyMCwibGFzdF92YWx1ZSI6IjEwMDc5NzkzNDIwIn0=",
          "node": {
            "title": "The Backpack"
          }
        },
        {
          "cursor": "eyJsYXN0X2lkIjoxMDA3OTc5NDM4MCwibGFzdF92YWx1ZSI6IjEwMDc5Nzk0MzgwIn0=",
          "node": {
            "title": "The Blouse"
          }
        }
      ]
    }
  },
  ...
}

https://shopify-graphiql-app.shopifycloud.com/login?return_to=%2F%3Fquery%3Dquery%2509%2528%2524numProducts%253A%2509Int%2521%252C%2509%2524cursor%253A%2509String%2529%257B%250A%2509%2509products%2528first%253A%2509%2524numProducts%252C%2509after%253A%2509%2524cursor%2529%2509%257B%250A%2509%2509%2509%2509pageInfo%2509%257B%250A%2509%2509%2509%2509%2509%2509hasNextPage%250A%2509%2509%2509%2509%2509%2509hasPreviousPage%250A%2509%2509%2509%2509%257D%250A%2509%2509%2509%2509edges%2509%257B%250A%2509%2509%2509%2509%2509%2509cursor%250A%2509%2509%2509%2509%2509%2509node%2509%257B%250A%2509%2509%2509%2509%2509%2509%2509%2509title%250A%2509%2509%2509%2509%2509%2509%257D%250A%2509%2509%2509%2509%257D%250A%2509%2509%257D%250A%257D%26variables%3D%257B%250A%2509%2509%2522numProducts%2522%253A%25093%250A%257D

このクエリは、接続の最初から 3 つの結果を返し、それらには各エッジのカーソルが含まれています。

次の例では、The Blouseのカーソルが接続結果の開始点として使用されています。この例では、接続のその時点以降の次の 3 つの結果を取得します。

POST /admin/api/2021-07/graphql.json

query ($numProducts: Int!, $cursor: String) {
  products(first: $numProducts, after: $cursor) {
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    edges {
      cursor
      node {
        title
      }
    }
  }
}

変数

{
  "numProducts": 3,
  "cursor": "eyJsYXN0X2lkIjoxMDA3OTc5NTc4OCwibGFzdF92YWx1ZSI6IjEwMDc5Nzk1Nzg4In0="
}

JSON レスポンス

{
  "data": {
    "products": {
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": true
      },
      "edges": [
        {
          "cursor": "eyJsYXN0X2lkIjoxMDA3OTc5NjMwMCwibGFzdF92YWx1ZSI6IjEwMDc5Nzk2MzAwIn0=",
          "node": {
            "title": "The Shorts"
          }
        },
        {
          "cursor": "eyJsYXN0X2lkIjoxMDA3OTc5NjY4NCwibGFzdF92YWx1ZSI6IjEwMDc5Nzk2Njg0In0=",
          "node": {
            "title": "The Jumper"
          }
        },
        {
          "cursor": "eyJsYXN0X2lkIjoxMDA3OTc5NzE5NiwibGFzdF92YWx1ZSI6IjEwMDc5Nzk3MTk2In0=",
          "node": {
            "title": "The Sneakers"
          }
        }
      ]
    }
  },
  ...
}

https://shopify-graphiql-app.shopifycloud.com/login?return_to=%2F%3Fquery%3Dquery%2509%2528%2524numProducts%253A%2509Int%2521%252C%2509%2524cursor%253A%2509String%2529%257B%250A%2509%2509products%2528first%253A%2509%2524numProducts%252C%2509after%253A%2509%2524cursor%2529%2509%257B%250A%2509%2509%2509%2509pageInfo%2509%257B%250A%2509%2509%2509%2509%2509%2509hasNextPage%250A%2509%2509%2509%2509%2509%2509hasPreviousPage%250A%2509%2509%2509%2509%257D%250A%2509%2509%2509%2509edges%2509%257B%250A%2509%2509%2509%2509%2509%2509cursor%250A%2509%2509%2509%2509%2509%2509node%2509%257B%250A%2509%2509%2509%2509%2509%2509%2509%2509title%250A%2509%2509%2509%2509%2509%2509%257D%250A%2509%2509%2509%2509%257D%250A%2509%2509%257D%250A%257D%26variables%3D%257B%250A%2509%2509%2522numProducts%2522%253A%25093%250A%257D

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Discussion

ログインするとコメントできます