GraphQL Mutations Tutorial

Summary

The administrative tasks in LogScale can be changed using the UI. However, they all can be performed from the command-line or as part of custom programs and scripts using the GraphQL API. These are done with GraphQL mutations.

Administrators and other authorized users may need to add or remove users, groups, and roles, which include permissions. They may also need to modify the configuration of a LogScale instance, as well as alerts and other actions. They can do this with a variety of GraphQL mutations that allow you to add, change, and delete administrative data stored in LogScale

This page covers general mutation syntax, how to execute a mutation, and how to get return values. For instructional purposes, generic mutations are used. Actual mutations include more components, and involve complexity that can be confusing when first learning about them. The goal here is to learn the basics of mutations.

Simple Generic Mutation

To begin, consider a very generic mutation — a fictitious one — called, addThing(). It's meant to add a given thing to a list of things stored in LogScale. Below is what its syntax might be:

graphql
addThing( 
      name: string!,
      enabled: boolean
         ): boolean

The syntax shows the input within parentheses — the spacing and line-breaks aren't necessary. Input is always given with a key and a value: the name is a key. You would give the name of the thing, the value as a string, within double-quotes. For the enabled value you would enter true or false. However, there isn't an exclamation mark after it. That means the parameter and value are not required. The default value would be used if not provided.

Exclamation marks are not typed. Neither is the colon after the closing parenthesis entered. Since the results in this syntax use a boolean, you don't enter anything for it. Here's how this fake mutation might be entered:

graphql
query {
      addThing( name: "thing-five" )
   }

You could enter this in the API Explorer, which is covered in another tutorial. Below are the imagined results from the mutation:

graphql
{
  "data": {
    "addThing": true
    }
}

These results indicate that the addition of the thing was successful. To get information on the thing added, you would use the fake query, thing(). It's covered on the Query Tutorials page. For a list of things, there might be a things() query.

Generic Datatype

The previous fictitious mutation is very simple. Most mutations, though, involve special datatypes — not just strings, booleans, or integers. Suppose the engineers that design LogScale decide to make a new version of addThing(), to replace it. They would mark the old version as deprecated, but it would still be useable for many weeks, months before it's eliminated. The new version would be called something like, addThingV2() — which is a common naming pattern they use. Here's its contrived syntax:

graphql
addThingV2( 
      name: string!,
      enabled: boolean
         ): Thing!

This uses an imagined datatype called, Thing. In the documentation that would accompany this mutation, a table would be provided with its components. Here's how that might look:

Table: Thing Datatype

Parameter Type Required Default Description
description string     A description of the thing.
enabled boolean yes   Whether the thing is enabled.
id string yes   The unique identifier of the thing.
name string yes   The display name of the thing.

As you can see in the table above, there are four possible values that are stored using the Thing datatype, four values that you can request in the results. They are listed alphabetically; you can enter them in any order. You'll notice that two are required and two are not. This doesn't mean you're required to request them. Instead, it means that some value must be stored in the fields that are required and the others can be null.

For the special datatype, you would list within curly-braces the keys for the values you want returned after executing the mutation. Here's how that might look:

graphql
query {
      addThingV2( name: "thing-six" )
      { name, id, enabled }
   }

The system will assign a unique identifier for the thing added. Below are the imagined results:

graphql
{
  "data": {
    "addThingV2": [
      {
        "name": "thing-six",
        "id": "mno123",
        "enabled": true
      }
}

This is in a json format that you can interpolate into variables in a custom program or script. Notice that it shows the thing is enabled, although that wasn't specified in the input for the mutation. That's because it has a default value.

Generic Update

For a mutation designed to add things, besides a query or two to get information on those things, there is usually a mutation to change things, and another delete them. There can also be a pair of mutations to enable and disable things.

To continue with these generic examples, suppose there is a mutation called, updateThing(). Here's how that might look in use:

graphql
query {
      updateThing( 
         id: "abc123",
         description: "The First Thing" )
      { name, enabled }
   }

This mutation changes, or rather gives a description to thing-one. Notice in the example the unique identifier for the thing is part of the input. This can be obtained from the related queries. Here are the supposed results of this mutation:

graphql
{
  "data": {
    "updateThing": [
      {
        "name": "thing-one",
        "enabled": true
      }
}

Since no error was returned, the change was successful. The results also confirm that the thing is already enabled.

Conclusion

There are more possibilities with mutations: how their syntax is composed, the use of special datatypes for input, the use of sub-datatypes for input and the results. This was only a start for understanding mutations and how they work.