GraphQL
Tutorial 9 - Using Mutations to Create New Records
17min
introduction so far, these tutorials have used graphql queries; in this article we're going to start looking at mutations the difference between queries and mutations is that queries "read" data from the database mutations "create", "update" or "delete" data keeping these types of operations separate is helpful, as it means you can be confident that running a query will not endanger the database on a live site "with great power comes great responsibility" when learning and testing graphql mutations, we strongly recommend you do so on a staging site if you need to test with real data, we recommend using the siteglide portal's site copy feature to create a staging site clone of a production site with a copy of the database siteglide may not be able to recover the exact state of data as it was before running a mutation which modifies that data see tutorial 11 using mutations to delete an item docid\ g9j0j4mc0ps0vxmooilyn for more tips on what to do if you accidentally delete data you didn't mean to (this won't help if you accidentally change the properties!) steps for creating a new record step 1 start with the mutation keyword all queries started with the query keyword; mutations start with the mutation keyword mutation namemymutation { } if using explorer, click the dropdown to select mutation instead of query, to unlock different options step 2) select the "record create" mutation type this will create a new record (or user create to create a new crm user ) mutation createwebappitem{ record create( ) { } } step 3 use the record object to define the new record the required record object allows you to define both the properties of the new record and which table it should belong to setting the table allows you to define which module or webapp it will belong to mutation createwebappitem{ record create( record { table "webapp 1", properties \[ { name "webapp field 1 1", value "foo" }, { name "webapp field 1 2", value "bar" } ] } ) {} } mutation createblogitem{ record create( record { table "module 3", properties \[ { name "module field 3 1", #title value "blog 1" }, { name "module field 3 3", #description value "lorem ipsum" }, { name "category array", value array \["1"] # where each item in the array is a category id ] } ) {} } as with queries, the explorer ui cannot handle multiple properties in a mutation you can use the explorer to figure out which individual property types are possible and then add the code manually properties itself can be written as an array with each object inside the array defining a property to set data types each property must have a name which matches the id of the field or custom field in siteglide when setting a value, you need to select a property value, value array, value boolean etc depending on the platformos type of data the field expects to figure out the correct one, you can reference this page field types docid\ snfmlvk7kh4k91klxxubh which will show which platformos types are used by each siteglide type to find out which siteglide types your table uses for each field, go to the corresponding webapp or module in the siteglide admin, or you can use this query to see each field's id and siteglide types together (you can also change the filter and properties to see which other tables are available) query inspectblogfieldsandtypes { admin forms(filter {name {value "module 3"}}) { results { fields } } } when using boolean, float or integer, you don't need to use quotes value booelan true, value float 3 456 step 4 add results while results are generally less useful in a mutation than in a query, having at least one result is generally required and your mutation won't work properly without it the idea is simply to give you information about the record in the database after the mutation to confirm that the mutation was successful even if this is simply an id mutations which affect multiple records at once often have a count result which only returns the number of records created you can add the results you need in the curly braces after the round brackets which follow record create mutation createblogitem{ record create( record { table "module 3", properties \[ { name "module field 3 1", value "blog 1" }, { name "module field 3 3", value "lorem ipsum" }, { name "category array", value array \["1"] ] } ) { id #note there is no need to add a results object here like you would in a query this returns the brand new item's automatically system generated id properties # returns an object containing the values of your properties which you passed in } } if successful, your results should return like this { "data" { "record create" { "id" "97", "properties" { "name" null, "slug" null, "og url" null, "address" null, "enabled" null, "og desc" null, "og type" null, "location" null, "og image" null, "og title" null, "meta desc" null, "weighting" null, "meta title" null, "expiry date" null, "release date" null, "twitter type" null, "category array" \[ "1" ], "module field 3 1" "blog 1", "module field 3 2" null, "module field 3 3" "lorem ipsum", "module field 3 4" null, "module field 3 5" null, "module field 3 6" null, "module field 3 7" null, "module field 3 8" null, "module field 3 9" null, "secure zone array" \[] } } } } if you have an error, the error information will display instead of the results in this case, value int was used instead of value for the blog item's title { "errors" \[ { "message" "argument 'value int' on inputobject 'propertyinputtype' has an invalid value (\\"blog 1\\") expected type 'int' ", "locations" \[ { "line" 6, "column" 9 } ], "path" \[ "mutation createblogitem", "record create", "record", "properties", 0, "value int" ], "extensions" { "code" "argumentliteralsincompatible", "typename" "inputobject", "argumentname" "value int" } } ] } step 5 pass in variables we covered variables in more detail in tutorial 6 variables docid\ e0hn2uwknz6i1qwyqsbmx but they are just as useful in mutations! in the following example, variables are added to pass in data programatically to create the new blog post mutation createblogitem($title string!, $description string!, $categories \[string]) { record create( record { table "module 3", properties \[ { name "module field 3 1", value $title }, { name "module field 3 3", value $description }, { name "category array", value array $categories ] } ) { id #note there is no need to add a results object here like you would in a query this returns the brand new item's automatically system generated id properties # returns an object containing the values of your properties which you passed in } } liquid {% assign description = "lorem ipsum" %} {% graphql createblogitem = "create blog item", title "the newest blog post", description description %} advanced using variables to pass in entire objects in graphql rather than single properties this is an advanced technique and you can skip it if you want to continue learning the basics of mutations if you like, you can use a variable to represent the entire properties object and pass in json which defines all the properties at once why? it might save time (or not), depending on the kind of data you have available it may also make the mutation more re usable learning advanced skills like this may give you more options as a developer and you may come across a situation where it's useful note how the parse json tag is used with literal square brackets to create a json array with nested objects defined by curly braces the category array property is an example of how you can pull in liquid from different sources into these properies, though this id would only contain a category id in for example a category detail layout mutation createblogitem($properties \[propertyinputtype!]!) { record create(record {table "module 3", properties $properties}) { id properties } } liquid {% parse json properties %} \[ { "name" "webapp field 3 1", "value" "blog title" }, { "name" "webapp field 3 3", "value" "lorem ipsum" }, { "name" "category array", "value array" \[{{this id}}] } ] {% endparse json %} {% graphql createblogitem = "create blog item", properties properties %} note, the structure of the json we are passing in the previous example is similar to the structure of properties in the mutation, but it is necessary in json to use double quotes around the keys like name , while the graphql syntax needs no quotes using explorer to turn properties into a variable is a quick way to reference the required type for the complex variable \[propertyinputtype] conclusion that's it! you should now be able to create siteglide webapp and module items programatically using mutations you could experiment with the user create mutation to create users instead of a record object this will have a user object which accepts a required email property related articles tutorial 8 building a liquid api get endpoint page powered by graphql queries docid\ l8stvoeogya5ejipwzzwu combining what you've learned in tutorial 8 and 9, you should be able to create an api where the liquid endpoint runs a mutation to create items you could use this alongside a custom form to allow the user to enter properties which are then passed to the endpoint in the url and then finally into the mutation via variables next time in the next tutorial, we'll look at more examples of mutations, including mutations to update and delete records