Creating and Updating Multiple Records in a Single Operation
This guide delves into the concept of mutations in 8base, focusing on their purpose, categories, and usage.
Overview
Mutations are critical operations that enable the creation, update, and deletion of data records.
8base's GraphQL engine auto-generates mutations as an integral part of the GraphQL schema, based on your workspace tables. Consequently, all workspace tables can process mutations through the workspace endpoint.
There are three broad categories of mutations:
- Single record mutations
- Related record mutations
- Update by filter mutations
Single Record Mutations
Single record mutations enable operations on individual records. This includes creating a new record, updating an existing one, or deleting it. The operations are typically in this format: tableNameCreate
, tableNameUpdate
, and tableNameDelete
.
For instance,
mutation {
userCreate(
data: {
email: "test@example.com"
firstName: "test"
lastName: "example"
}
) {
id
email
firstName
lastName
}
}
This example illustrates the creation of a new user in the User table.
Creating a single record
You can create a new record using the data argument that defines the records data:
mutation {
authorCreate(
data: { name: "Wyatt" }
) {
id
name
}
}
# Response:
{
"data": {
"authorCreate": {
"id": "ck0d12w8e01c001l1dtxz5b7f",
"name": "Wyatt"
}
}
}
Updating a Single Record
You can also update a record using the data argument while including the records id
or using a filter
that includes a unique field.
mutation {
# Updates record name with find by unqiue name)
quade: authorUpdate(
filter: { name: "Quade" }
data: {
name: "PenPossum"
}
) {
id
name
}
# Updates record with (find by id)
wyatt: authorUpdate(
data: {
id: "ck0d12w8e01c001l1dtxz5b7f"
name: "Hyatt"
}
) {
id
name
}
}
# Response:
{
"data": {
"quade": {
"id": "ck0d12nf001bu01l15skw13pg",
"name": "PenPossum"
},
"wyatt": {
"id": "ck0d12w8e01c001l1dtxz5b7f",
"name": "Hyatt"
}
}
}
Deleting a Single Record
You can delete a record using the data argument while including the records id
or using a filter
that includes a unique field.
mutation {
# Deletes record by unqiue field.
quade: authorDelete(filter: {
name: "PenPossum"
}) {
success
}
# Deletes record by id.
wyatt: authorDelete(data: {
id: "ck0d12w8e01c001l1dtxz5b7f"
}) {
success
}
}
# Response:
{
"data": {
"quade": {
"success": true
},
"wyatt": {
"success": true
}
}
}
When handling delete mutations, an additional force parameter can be specified in the data object that accepts a boolean value. The default value is false
. When set to true
, it will force a cascading delete on the record. This means that if the record being deleted is a parent in a mandatory relationship with child records, all child records will be deleted as well.
Related Record Mutations
Related record mutations enable creating multiple related records in one operation. This is particularly useful when dealing with relationships.
For example:
mutation {
userCreate(
data: {
email: "test@example.com"
firstName: "test"
lastName: "example"
posts: {
create: [
{
title: "first post"
content: "content of the first post"
}
{
title: "second post"
content: "content of the second post"
}
]
}
}
) {
id
email
firstName
lastName
posts {
items {
id
title
content
}
}
}
}
In this example, a new user is created along with two associated posts.
You can create, connect, reconnect, and disconnect related table records using 8base's auto-generated GraphQL mutation operations.
- Create: Create and relate child objects.
- Connect: Connect existing objects in addition to already connected objects.
- Reconnect: Replace old connected objects with a new set of connected objects (update mutation only).
- Disconnect: Disconnect connected objects (update mutation only).
Creating Related Records in Nested Mutation
When creating or updating a parent record, one or more child records can be created using create
.
mutation {
authorUpdate(filter: {
name: "Huxley"
},
data: {
bio: "Just a guy who loves possum.",
posts: {
create: [{
title: "Can't stop the Possum",
body: "Cause Possum is Awesome",
publishingDate: "2019-09-22T03:45:33.432Z"
}]
}
}) {
posts(last: 1) {
items {
title
}
}
}
}
# Response:
{
"data": {
"authorUpdate": {
"posts": {
"items": [
{
"title": "Can't stop the Possum"
}
]
}
}
}
}
Connecting Records in Mutation
One or more records can be connected using a mutation that associates them, whether the relationship is many-to-many, one-to-many, or one-to-one.
# The author gets changed to the author named "Stevens" using connect.
mutation {
postUpdate(filter: {
title: "Can't stop the Possum"
},
data: {
author: {
connect: {
name: "Stevens"
}
}
}) {
title
author {
name
}
}
}
# Response:
{
"data": {
"postUpdate": {
"title": "Can't stop the Possum",
"author": {
"name": "Stevens"
}
}
}
}
Re-connecting Records in a Mutation
All related records can be dissasociated from a record, while connecting one or more in a specified set.
# All posts belonging to the author Huxley are changed to the new set.
mutation {
authorUpdate(filter: {
name: "Huxley"
},
data: {
posts: {
reconnect: [{
id: "ck08eum6101qf01l9cn6v35v4"
}, {
id: "ck08eve7t01r701l9fsg9a4ow"
}]
}
}) {
name
posts {
count
items {
title
}
}
}
}
# Response:
{
"data": {
"authorUpdate": {
"name": "Huxley",
"posts": {
"count": 2,
"items": [
{
"title": "Awesome Possum"
},
{
"title": "Pt.2 of the Possum Trilogy"
}
]
}
}
}
}
Disconnecting Records in a Mutation
One or more records can be disconnected using a mutation, whether the relationship is many-to-many, one-to-many, or one-to-one. If the relationship is mandatory, an error will be raised.
# All posts belonging to the author Huxley are changed to the new set.
mutation {
authorUpdate(filter: {
name: "Huxley"
},
data: {
publications: {
disconnect: [{
id: "ck0d2peue00sg01l36w2q2gdo"
}, {
id: "ck0d2q07g00sx01l340mt7lh9"
}]
}
}) {
name
publications {
count
}
}
}
Updating Using Filter Mutations
You can update multiple records concurrently using a filter. The operations are typically in the format tableNameUpdateByFilter
and tableNameDeleteByFilter
.
For instance,
mutation {
userUpdateByFilter(
filter: {
email: {
equals: "test@example.com"
}
}
data: {
lastName: {
set: "New lastName"
}
}
) {
items {
lastName
}
}
}
This example demonstrates how to update the lastName
of all users that have their email
equal to test@example.com
.
You can update multiple table records using 8base's auto-generated GraphQL mutation operations.
Updating the Titles of All Posts Published Before a Specific Day
Prefix the title of every post published before a specific date with the string "LEGACY: ".
mutation {
postUpdateByFilter(
data: {
title: {
prefix: "LEGACY: "
}
},
filter: {
publishingDate: {
lt: "2020-06-05"
}
}) {
count
items {
title
}
}
}
# Response:
{
"data": {
"postUpdateByFilter": {
"count": 3,
"items": [
{
"title": "LEGACY: My Post"
},
{
"title": "LEGACY: My Other Post"
},
{
"title": "LEGACY: My Other Awesome Post"
}
]
}
}
}
Field Type Predicates
When using the tableNameUpdateByFilter
operation, different field types have different functions that can be used.
When running the updateByFilter
operation, only one coercive method can be used at a time per field.
String
- prefix: String - Prepends a supplied string to the field's existing value.
- postfix: String - Appends a supplied string to the field's existing value.
- set: String - Sets a supplied string as the field's new value.
For example:
mutation {
postUpdateByFilter(data: { aTextTypeField: { postfix: " - ADD ME AFTER" } }) {
items {
aTextTypeField
}
}
}
Number
- add: Int - Adds a supplied Int to the field's existing value.
- sub: Int - Subtracts a supplied Int from the field's existing value.
- mult: Int - Multiply a supplied Int by the field's existing value.
- dev: Int - Divide the field's existing value by a supplied Int.
- mod: Int - Modulo the field's existing value by a supplied Int.
- set: Int - Sets a supplied Int as the field's new value.
- pow: Int - Raise the field's existing value to the exponent of a supplied Int.
- sqrt: Boolean - Set the field's existing value to its square root (use
true
orfalse
).
For example:
mutation {
postUpdateByFilter(data: { aNumberTypeField: { pow: 10 } }) {
items {
aNumberTypeField
}
}
}
Date
set: String - Sets a supplied Date as the field's new value.
add:
UpdateByFilterDatePartsInput
- Adds a given number of days, months, years, hours, minutes, seconds, and microseconds to the field's existing value.sub:
UpdateByFilterDatePartsInput
- Subtracts a given number of days, months, years, hours, minutes, seconds, and microseconds from the field's existing value.
For example:
mutation {
postUpdateByFilter(
data: {
aDateTypeField: {
add: {
years: 1
months: 3
days: 20
hours: 13
seconds: 22
microseconds: 980
}
}
}
) {
items {
aDateTypeField
}
}
}
Switch
- set: Boolean|String - Set the field's existing value to a supplied Boolean or String value.
- invert: Boolean - Switches the field's existing value to its Boolean opposite (
true -> false
,false -> true
).
For example:
mutation {
postUpdateByFilter(data: { aSwitchTypeField: { set: "CUSTOM_OPTION" } }) {
items {
aSwitchTypeField
}
}
}
JSON
- set: JSON - Set the field's existing value to a supplied JSON object.
For example:
mutation {
postUpdateByFilter(
data: { aJsonTypeField: { set: { hey: "HO!", lets: "GO!" } } }
) {
items {
aJsonTypeField
}
}
}