Search code examples
graphqlgithub-apigithub-graphql

How can I pass multiple cursors to a single GitHub GraphQL query with multiple node ids?


I'm trying to batch my GraphQL queries to retrieve the data I need from multiple repositories with the same request, where each repository has a different cursor.

Assuming I have the IDs of 3 nodes and only 2 cursors with the following mapping:

NODE_ID_1 <-> CURSOR_X
NODE_ID_2 <-> Empty
Node_ID_3 <-> CURSOR_Y

How can I populate the GraphQL query so that I can query all 3 nodes, but pass their respective cursors?

query {
  nodes(ids: ["NODE_ID_1", "NODE_ID_2", "NODE_ID_3"]) {
    ... on Repository {
      databaseId
      stargazers(first: 100, after:???) {
        pageInfo {
          endCursor
        }
        edges {
          starredAt
        }
      }
    }
  }
}

Solution

  • You can use aliases by iterating over nodes and map them to a field name like nodeX :

    {
      node1: node(id: "MDEwOlJlcG9zaXRvcnkxMDQ4MzQ4") {
        ... on Repository {
          ...Repo
        }
      }
      node2: node(id: "MDEwOlJlcG9zaXRvcnkyMzE5NDk4") {
        ... on Repository {
          ...Repo
        }
      }
      node3: node(id: "MDEwOlJlcG9zaXRvcnkyMzI1Mjk4") {
        ... on Repository {
          ...Repo
        }
      }
    }
    
    fragment Repo on Repository {
      name
    }
    

    output:

    {
      "data": {
        "node1": {
          "name": "DROP5.0"
        },
        "node2": {
          "name": "subsurface"
        },
        "node3": {
          "name": "linux"
        }
      }
    }
    

    For the cursor value you just need to map the field name to both the node id and the cursor value:

    {
      node1: node(id: "MDEwOlJlcG9zaXRvcnkyMzE5NDk4") {
        ... on Repository {
          name
          stargazers(first: 1, after:"Y3Vyc29yOnYyOpIAzR1p") {
            pageInfo {
              endCursor
            }
            edges {
              starredAt
            }
          }
        }
      }
      node2: node(id: "MDEwOlJlcG9zaXRvcnkxMDQ4MzQ4") {
        ... on Repository {
          name
          stargazers(first: 1, after: null) {
            pageInfo {
              endCursor
            }
            edges {
              starredAt
            }
          }
        }
      }
      node3: node(id: "MDEwOlJlcG9zaXRvcnkyMzI1Mjk4") {
        ... on Repository {
          name
          stargazers(first: 1, after:"Y3Vyc29yOnYyOpIAzQzi") {
            pageInfo {
              endCursor
            }
            edges {
              starredAt
            }
          }
        }
      }
    }
    

    In this case your input map would look like:

    input = {
        "node1": {
            "id": "MDEwOlJlcG9zaXRvcnkyMzE5NDk4",
            "cursor": "Y3Vyc29yOnYyOpIAzR1p"
        },
        "node2": {
            "id": "MDEwOlJlcG9zaXRvcnkxMDQ4MzQ4",
            "cursor": null
        },
        "node3": {
            "id": "MDEwOlJlcG9zaXRvcnkyMzI1Mjk4",
            "cursor": "Y3Vyc29yOnYyOpIAzQzi"
        }
    }
    

    With variables:

    query ($id1: ID!, $cursor1: String, $id2: ID!, $cursor2: String, $id3: ID!, $cursor3: String) {
      node1: node(id: $id1) {
        ... on Repository {
          name
          stargazers(first: 1, after: $cursor1) {
            pageInfo {
              endCursor
            }
            edges {
              starredAt
            }
          }
        }
      }
      node2: node(id: $id2) {
        ... on Repository {
          name
          stargazers(first: 1, after: $cursor2) {
            pageInfo {
              endCursor
            }
            edges {
              starredAt
            }
          }
        }
      }
      node3: node(id: $id3) {
        ... on Repository {
          name
          stargazers(first: 1, after: $cursor3) {
            pageInfo {
              endCursor
            }
            edges {
              starredAt
            }
          }
        }
      }
    }
    

    variables :

    {
      "id1": "MDEwOlJlcG9zaXRvcnkyMzE5NDk4",
      "cursor1": "Y3Vyc29yOnYyOpIAzR1p",
      "id2": "MDEwOlJlcG9zaXRvcnkxMDQ4MzQ4",
      "cursor2": null,
      "id3": "MDEwOlJlcG9zaXRvcnkyMzI1Mjk4",
      "cursor3": "Y3Vyc29yOnYyOpIAzQzi"
    }