Schema tutorial
Schema tutorialLesson 7: Adapting content in bulk

Lesson 7: Adapting content in bulk

This tutorial lesson adapts content in bulk, updating the title, content and excerpt for multiple posts with a single GraphQL request.

For this GraphQL query to work, the Schema Configuration applied to the endpoint needs to have Nested Mutations enabled

The GraphQL query below retrieves the data for the multiple posts, executes a search and replace on the title, content and excerpt fields for each of them, adapts these as inputs to the mutation, and exports a single dynamic variable $postInputs with all the results as a dictionary, with format:

{
  "${post ID}": {
    "title": "${adapted post title}",
    "excerpt": "${adapted post excerpt}"
  },
  // repeat for all other posts ...
}

In the mutation operation, each of these entries is then retrieved via _objectProperty (using ${post ID} as the key) and passed as the input to update the post:

query TransformAndExportData(
  $limit: Int! = 5,
  $offset: Int! = 0,
  $replaceFrom: [String!]!
  $replaceTo: [String!]!
) {
  posts: posts(
    pagination: { limit: $limit, offset: $offset }
    sort: { by: ID, order: ASC }
  ) {
    rawTitle
    rawContent
    rawExcerpt
      @strReplaceMultiple(
        search: $replaceFrom
        replaceWith: $replaceTo
        affectAdditionalFieldsUnderPos: [1, 2]
      )
      @deferredExport(
        as: "postAdaptedSources"
        type: DICTIONARY
        affectAdditionalFieldsUnderPos: [1, 2]
      )
  }
}
 
query AdaptDataForMutationInput
  @depends(on: "TransformAndExportData")
{
  postInputs: _echo(value: $postAdaptedSources)
    @underEachJSONObjectProperty(
      passValueOnwardsAs: "adaptedSource",
      affectDirectivesUnderPos: [1, 2, 3, 4]
    )
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $adaptedSource,
          by: {
            key: "rawTitle"
          }
        },
        passOnwardsAs: "adaptedTitle"
      )
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $adaptedSource,
          by: {
            key: "rawExcerpt"
          }
        },
        passOnwardsAs: "adaptedExcerpt"
      )
      @applyField(
        name: "_objectProperty",
        arguments: {
          object: $adaptedSource,
          by: {
            key: "rawContent"
          }
        },
        passOnwardsAs: "adaptedContent"
      )
      @applyField(
        name: "_echo",
        arguments: {
          value: {
            title: $adaptedTitle,
            excerpt: $adaptedExcerpt,
            contentAs: {
              html: $adaptedContent
            }
          }
        },
        setResultInResponse: true
      )
    @export(as: "postInputs")
}
 
mutation UpdatePost(
  $limit: Int! = 5,
  $offset: Int! = 0
)
  @depends(on: "AdaptDataForMutationInput")
{
  adaptedPosts: posts(
    pagination: { limit: $limit, offset: $offset }
    sort: { by: ID, order: ASC }
  ) {
    id
    postInput: _objectProperty(
      object: $postInputs,
      by: { key: $__id }
    ) @remove
    update(input: $__postInput) {
      status
      errors {
        __typename
        ...on ErrorPayload {
          message
        }
      }
      post {
        title
        content
        excerpt
      }
    }
  }
}
  • The Field on Field extension provides directive @applyField which, invoked with _objectProperty, extracts the properties from each item in the JSON object (passed as $adaptedSource), and then with _echo, it creates the corresponding JSON input with those properties
  • In addition to function fields, the PHP Functions via Schema extension also provides functionality via their corresponding "function directives", such as @strReplaceMultiple
  • When Multi-Field Directives is enabled, we can apply a directive to more than one field, indicating the relative position(s) of the additional field(s) via argument affectAdditionalFieldsUnderPos
  • When applying a directive to some field and then exporting its value, we must use @deferredExport instead of @export
  • When using Multi-Field Directives together with @export( or @deferredExport), the exported value is a JSON object containing all the fields
  • Mutation Post.update is available in the schema only when the Nested Mutations feature is enabled