Execute Multiple Queries in Sequence

Sequence a series of queries into a single result

The @sequence directive is a custom StepZen directive that enables you to execute multiple queries in a sequence that returns a single result. Each step in the sequence passes data to the next, enabling data from step 1 in a sequence to be used as arguments to step 2 in a sequence and so on. This allows for complex sequencing of API and database calls to populate a query without the need to write difficult asynchronous call handling.

Configuration Properties

steps

The only required argument to create a sequence is the steps that make up that sequence. This is an array of objects that the query steps through. Each object in the array must contain (at a minimum) the name of the query that the step will call.

@sequence(
  steps:
    [
      {query: "step1"}
      {query: "step2"}
    ]
)

The value of query must be a query that is defined on the schema. The result of the sequence will be the same as the result of the last step (step2 in this case).

The steps are executed in the order they are listed (from top to bottom). For more details on how to override the steps to include data from prior steps, see the Collecting Results section below.

In some cases, the name of a property returned by a query does not match the argument name for the subsequent query.

For example, let's imagine the step1 query above returns lastName, but the step2 query expects an argument of surname. In these scenarios, you can use arguments to map the results to the expected name.

@sequence(
  steps:
    [
      {query: "step1"}
      {query: "step2", arguments: [{name: "surname", field: "lastName"}]}
    ]
)

Collecting Results

By default, the result of the final step is the result of the sequence. However, in some scenarios, you may need data from prior steps as part of the result of the entire sequence.

For example, imagine step1 returns user information including their name but step2 returns location information including city. If you wanted the full sequence to return both name and city, you can use an extra step in the sequence that calls a query utilizing a special echo connector.

The sequence would look like:

@sequence(
  steps:
    [
      {query: "step1"}
      {query: "step2"}
      {query: "collect"}
    ]
)

The collect query in step 3 of the sequence would then use the echo connector:

collect (name: String!, city: String!): UserWithLocation
    @connector (type: "echo")

For a more detailed walkthrough of how @sequence can be used, follow our sequencing queries tutorial.

Authorization Headers in the GraphQL Schema

In some cases, such when running an @sequence directive, GraphQL arguments can be passed as header variables in an HTTP request.

Take the example below, where an argument of access_token: String is passed to the authorization header as a bearer token:

type Query {
    id: String 
}

type Query {
    my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "$access_token" }]
        )
}

Query

When running the GraphQL query, the access_token: String argument is "Bearer CMORsM63LxIO...", and contains the entire string for the Authorization header.

query MyQuery {
  my_query(
    access_token: "Bearer CMORsM63LxIO_4eBAEBAgAAMAEAAAAYY_MDnCSCXsaQLKM_AFzIUdnIEl9qo7Cwj2t1Z_rNAec5zYls6LgB_b8f_BwyE_wf8_-D_fc4sAAAAYAYY9DwfIBgcgA_gwx8GGQAAOIUnAADgAOBCFBZjpguluSl9IBk0ni7_U1o-pPgjSgNuYTFSAFoA"
  ) {
    id
  }
}

If there is no access_token provided in the query, StepZen recognizes the null parameter and will resolve the Authorization header to an empty string, "".

This is an example query where there is no access_token argument provided:

query MyQuery {
  my_query {
    id
  }
}

Authorization: "null" is converted to Authorization: "" to prevent errors from the server, and keeps unwanted null parameters from being sent as headers.

Combining Variables with Strings in Authorization headers

StepZen also supports strings combined with variables in header parameters.

As shown in the schema, my_query will combine argument access_token with Bearer.

my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "Bearer $access_token" }]
        )

When my_query is executed, access_token does not need to contain the Bearer string. The schema combines the Bearer string with the access_token.

query MyQuery {
  my_query(
    access_token: "CMORsM63LxIO_4eBAEBAgAAMAEAAAAYY_MDnCSCXsaQLKM_AFzIUdnIEl9qo7Cwj2t1Z_rNAec5zYls6LgB_b8f_BwyE_wf8_-D_fc4sAAAAYAYY9DwfIBgcgA_gwx8GGQAAOIUnAADgAOBCFBZjpguluSl9IBk0ni7_U1o-pPgjSgNuYTFSAFoA"
  ) {
    id
  }
}

The request going to the endpoint https://api.example.com/v1/api/ will still send the Authorization header the same way it did previously, "Authorization": "Bearer CMORsM63LxIO...".

@Sequence example of passing access_token as a variable

Let's say there is an @sequence that sends the_access_token but does not provide the token type Bearer in the string.

Note: Refer to @sequence documentation to understand the how this sequence passes variables between queries.

You do not need to understand @sequence in full detail, to understand how StepZen uses the access_token to support Authorization headers.

Here is an example:

type Auth {
    access_token: String!
    token_type: String!
    expires_in: String!
}

type Query {
    id: String 
}

type Query {
    get_auth: Auth
        @rest(
            method: POST
            contenttype: "application/x-www-form-urlencoded"
            endpoint: "https://api.example.com/v1/api?username={{.Get \"username\" }}&password={{.Get \"password\" }}"
            configuration: "configs"
        )
    my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "Bearer $access_token" }]
        )
    """
    returns a query with the new access_token
    """
    query_with_key: Query
        @sequence(
            steps: [
                { query: "get_auth" }
                { query: "my_query" }
            ]
        )
}

type Auth has the field access_token. In the query_with_key @sequence, the get_auth query passes the access_token to the my_query query.

{
    "token_type": "bearer",
    "refresh_token": "12314-3ee9-4a6b-bc87-134254332",
    "access_token": "CMORsM63LxIO_4eBAEBAgAAMAEAAAAYY_MDnCSCXsaQLKM_AFzIUdnIEl9qo7Cwj2t1Z_rNAec5zYls6LgB_b8f_BwyE_wf8_-D_fc4sAAAAYAYY9DwfIBgcgA_gwx8GGQAAOIUnAADgAOBCFBZjpguluSl9IBk0ni7_U1o-pPgjSgNuYTFSAFoA",
    "expires_in": 21600
}

As shown above:

  • access_token (generated by the first step)
  • get_auth does not have Bearer preceding the token generated

Therefore my_query must be written with headers: [{ name: "Authorization", value: "Bearer $access_token" }]. StepZen combines the variable access_token being passed in the first step with Bearer added in the schema, to properly execute the Authorization header.

my_query(access_token: String): Query
        @rest (
            endpoint: "https://api.example.com/v1/api/"
            headers: [{ name: "Authorization", value: "Bearer $access_token" }]
        )

This site uses cookies: By using this website, you consent to our use of cookies in accordance with our Website Terms of Use and Cookie Policy.