Skip to main content

Update

GraphQL allows to query and mutate data. Mutations are operations like create, update and delete. This chapter describes how data can be updated.

API Approaches

OctoMesh provides two ways to update entities:

ApproachEndpointUse Case
Typedruntime.[typeName].updateStrongly typed, IDE autocompletion, compile-time validation
Genericruntime.runtimeEntities.updateDynamic type handling, flexible attribute specification

Generic Update Mutation

The generic runtimeEntities.update mutation allows updating entities of any type by specifying the rtId and attributes dynamically. This is useful when the type is not known at compile time or when building dynamic applications.

Basic Generic Update

mutation {
runtime {
runtimeEntities {
update(
entities: [
{
rtId: "69692194d66195e5364c310f"
item: {
ckTypeId: "Basic/TreeNode"
attributes: [
{ attributeName: "name", value: "Updated Name" }
{ attributeName: "Description", value: "New description" }
]
}
}
]
) {
rtId
ckTypeId
attributes {
items {
attributeName
value
}
}
}
}
}
}

The result will be:

{
"data": {
"runtime": {
"runtimeEntities": {
"update": [
{
"rtId": "69692194d66195e5364c310f",
"ckTypeId": "Basic/TreeNode",
"attributes": {
"items": [
{ "attributeName": "name", "value": "Updated Name" },
{ "attributeName": "Description", "value": "New description" }
]
}
}
]
}
}
}
}

Generic Batch Update

Multiple entities can be updated in a single mutation:

mutation {
runtime {
runtimeEntities {
update(
entities: [
{
rtId: "69692194d66195e5364c310f"
item: {
ckTypeId: "Basic/TreeNode"
attributes: [
{ attributeName: "name", value: "Node 1 Updated" }
]
}
},
{
rtId: "69692194d66195e5364c3110"
item: {
ckTypeId: "Basic/TreeNode"
attributes: [
{ attributeName: "name", value: "Node 2 Updated" }
]
}
}
]
) {
rtId
ckTypeId
}
}
}
}

Generic Update Input Structure

FieldTypeRequiredDescription
rtIdOctoObjectIdYesRuntime identifier of the entity to update
itemGenericEntityInputYesThe update payload

GenericEntityInput:

FieldTypeRequiredDescription
ckTypeIdStringYesConstruction Kit type identifier (e.g., Basic/TreeNode)
attributes[AttributeInput]NoArray of attribute name-value pairs to update

AttributeInput:

FieldTypeDescription
attributeNameStringName of the attribute to update
valueSimpleScalarNew value for the attribute
note

Only the attributes specified in the attributes array will be updated. Other attributes remain unchanged.


Typed Update Mutation

The typed approach uses type-specific endpoints with strongly typed input objects. This provides better IDE support and compile-time validation.

Simple update mutation

The area runtime allows access to entities of the Runtime Model. To update an entity, you need to provide the rtId of the entity and the fields you want to update.

mutation {
runtime {
industryEnergyEnergyMeters {
update(
entities: [
{
rtId: "662532d5241639b42933057e"
item: {
voltage: 235
state: ON
name: "Updated Energy Meter"
}
}
]
) {
rtId
voltage
state
name
}
}
}
}

This mutation will update the energy meter with the given rtId. Only the fields provided in the mutation will be updated. The result will be:

{
"data": {
"runtime": {
"industryEnergyEnergyMeters": {
"update": [
{
"rtId": "662532d5241639b42933057e",
"voltage": 235,
"state": "ON",
"name": "Updated Energy Meter"
}
]
}
}
}
}

Update with variables

For more complex updates, it is recommended to use GraphQL variables. The input type for updates follows the naming convention [TypeName]InputUpdate.

mutation updateMeshAdapter($entities: [SystemCommunicationMeshAdapterInputUpdate]!) {
runtime {
systemCommunicationMeshAdapters {
update(entities: $entities) {
rtId
ckTypeId
name
description
configuration
imageName
imageVersion
deploymentState
}
}
}
}

Variables:

{
"entities": [
{
"rtId": "65d5c447b420da3fb12381bc",
"item": {
"name": "Updated Adapter Name",
"configuration": "{\"host\": \"localhost\", \"port\": 8080}"
}
}
]
}

Batch updates

Multiple entities can be updated in a single mutation by providing an array of entities:

mutation {
runtime {
industryEnergyEnergyMeters {
update(
entities: [
{
rtId: "662532d5241639b42933057e"
item: {
state: ON
}
},
{
rtId: "65dc6d24cc529cdc46c84fcc"
item: {
state: OFF
}
}
]
) {
rtId
state
}
}
}
}

Update with nested objects

For entities with nested objects like records, the entire nested object must be provided:

mutation updateCustomer($customer: EnergyCommunityCustomerInputUpdate!) {
runtime {
energyCommunityCustomers {
update(entities: [$customer]) {
rtId
contact {
firstName
lastName
email
address {
street
zipcode
cityTown
}
}
bankAccount {
iban
accountHolder
}
}
}
}
}

Variables:

{
"customer": {
"rtId": "667acc3be06025c7329fc57c",
"contact": {
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"address": {
"street": "Main Street 1",
"zipcode": "12345",
"cityTown": "Berlin"
}
},
"bankAccount": {
"iban": "DE89370400440532013000",
"accountHolder": "John Doe"
}
}
}

Input type naming convention

OperationInput Type PatternExample
Create[TypeName]InputSystemCommunicationMeshAdapterInput
Update[TypeName]InputUpdateSystemCommunicationMeshAdapterInputUpdate

The key difference is that update input types always require the rtId field to identify the entity to update.


Updating Special Scalar Types

Updating TimeSpan Attributes

TimeSpan attributes are updated by providing the new value in seconds (decimal number).

Typed Update with TimeSpan

mutation {
runtime {
octoSdkDemoMeteringPoints {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
# Update interval from 15 minutes to 30 minutes
dataTransmissionInterval: 1800
}
}
]
) {
rtId
meteringPointNumber
dataTransmissionInterval
}
}
}
}

Generic Update with TimeSpan

mutation {
runtime {
runtimeEntities {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
ckTypeId: "OctoSdkDemo/MeteringPoint"
attributes: [
# Update to 1 hour interval
{ attributeName: "dataTransmissionInterval", value: 3600 }
]
}
}
]
) {
rtId
attributes(first: 10) {
items {
attributeName
value
}
}
}
}
}
}

Updating Complex Attribute Types

OctoMesh supports updating complex attribute types including Record, RecordArray, Binary, and BinaryLinked.

Example Model

The examples below use the OctoSdkDemo/Customer type from the Octo.Sdk.Demo Construction Kit, which includes:

  • contact - Record (with nested address Record)
  • bankAccount - Record
  • notes - RecordArray of CustomerNote
  • profilePicture - Binary (inline binary data)
  • contractDocument - BinaryLinked (external file reference)

Updating Record Attributes

When updating a Record attribute, provide the complete record structure. Record updates replace the entire record value.

Typed Update with Record

Update the customer's contact information:

mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
contact: {
legalEntityType: NATURAL_PERSON
firstName: "John"
lastName: "Doe-Smith" # Changed last name
email: "john.doe-smith@newmail.com" # New email
address: {
street: "456 New Avenue" # New address
zipcode: 10117
cityTown: "Berlin"
nationalCode: "DE"
}
}
}
}
]
) {
rtId
contact {
firstName
lastName
email
address {
street
cityTown
}
}
}
}
}
}

Generic Update with Record

mutation {
runtime {
runtimeEntities {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
ckTypeId: "OctoSdkDemo/Customer"
attributes: [
{
attributeName: "contact"
value: {
legalEntityType: "NATURAL_PERSON"
firstName: "John"
lastName: "Doe-Smith"
email: "john.doe-smith@newmail.com"
address: {
street: "456 New Avenue"
zipcode: 10117
cityTown: "Berlin"
nationalCode: "DE"
}
}
}
]
}
}
]
) {
rtId
attributes(first: 10) {
items {
attributeName
value
}
}
}
}
}
}

Updating RecordArray Attributes

RecordArray updates replace the entire array. To add items, include all existing items plus the new ones.

Typed Update with RecordArray

Add a new note to the customer's notes:

mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
notes: [
# Existing notes (must be included to keep them)
{
date: "2024-01-15T10:30:00Z"
text: "Initial contact - interested in premium plan"
author: "Sales Team"
category: "Sales"
}
{
date: "2024-01-20T14:00:00Z"
text: "Contract signed"
author: "Account Manager"
category: "Contract"
}
# New note
{
date: "2024-03-01T09:00:00Z"
text: "Customer requested support for billing inquiry"
author: "Support Team"
category: "Support"
}
]
}
}
]
) {
rtId
notes {
date
text
author
category
}
}
}
}
}

Generic Update with RecordArray

mutation {
runtime {
runtimeEntities {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
ckTypeId: "OctoSdkDemo/Customer"
attributes: [
{
attributeName: "notes"
value: [
{
date: "2024-01-15T10:30:00Z"
text: "Initial contact"
author: "Sales Team"
category: "Sales"
}
{
date: "2024-03-01T09:00:00Z"
text: "New support request"
author: "Support Team"
category: "Support"
}
]
}
]
}
}
]
) {
rtId
attributes(first: 10) {
items {
attributeName
value
}
}
}
}
}
}

Updating Binary Attributes

Binary attributes store inline binary data as byte arrays. Updates replace the entire binary data.

Typed Update with Binary

mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
# Update profilePicture with new image data (PNG header bytes as example)
profilePicture: [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82]
}
}
]
) {
rtId
profilePicture
}
}
}
}

Generic Update with Binary

mutation {
runtime {
runtimeEntities {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
ckTypeId: "OctoSdkDemo/Customer"
attributes: [
{
attributeName: "profilePicture"
value: [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82]
}
]
}
}
]
) {
rtId
attributes(first: 10) {
items {
attributeName
value
}
}
}
}
}
}

Clearing Binary Attributes

To remove binary data, set the attribute to null:

mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
profilePicture: null # Remove profilePicture
}
}
]
) {
rtId
profilePicture
}
}
}
}

Clearing Record and RecordArray Attributes

To clear a Record or RecordArray attribute, set it to null:

mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
bankAccount: null # Remove bank account
notes: null # Clear all notes
}
}
]
) {
rtId
bankAccount {
iban
}
notes {
text
}
}
}
}
}

Updating Multiple Complex Attributes

You can update multiple complex attributes in a single mutation:

mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
customerStatus: ACTIVE
phoneNumberMobile: "+49 171 9999999"
# Update contact Record
contact: {
legalEntityType: NATURAL_PERSON
firstName: "Max"
lastName: "Mustermann"
email: "max.mustermann@updated.com"
address: {
street: "Neue Straße 100"
zipcode: 10119
cityTown: "Berlin"
nationalCode: "DE"
}
}
# Add bank account Record
bankAccount: {
iban: "DE89370400440532013000"
swiftCode: "COBADEFFXXX"
accountHolder: "Max Mustermann"
}
# Update notes RecordArray
notes: [
{
date: "2024-01-10T09:00:00Z"
text: "Customer data updated"
author: "Admin"
category: "Update"
}
]
}
}
]
) {
rtId
customerStatus
phoneNumberMobile
contact {
firstName
lastName
email
address {
street
cityTown
}
}
bankAccount {
iban
accountHolder
}
notes {
date
text
author
}
}
}
}
}

Partial Record Updates

caution

Record attributes do not support partial updates. When updating a Record, you must provide all required fields. Optional fields that are not provided will be cleared.

If you need to update only specific fields within a Record, first query the current values, merge your changes, then send the complete record:

# Step 1: Query current values
query {
runtime {
octoSdkDemoCustomers(rtIds: ["693c5b93464d7d9e1396cf1c"]) {
items {
contact {
legalEntityType
firstName
lastName
email
address {
street
zipcode
cityTown
nationalCode
}
}
}
}
}
}

# Step 2: Update with merged values (only changing email)
mutation {
runtime {
octoSdkDemoCustomers {
update(
entities: [
{
rtId: "693c5b93464d7d9e1396cf1c"
item: {
contact: {
legalEntityType: NATURAL_PERSON # Keep original
firstName: "John" # Keep original
lastName: "Doe" # Keep original
email: "john.doe@newemail.com" # Updated value
address: {
street: "123 Main Street" # Keep original
zipcode: 10115 # Keep original
cityTown: "Berlin" # Keep original
nationalCode: "DE" # Keep original
}
}
}
}
]
) {
rtId
contact {
firstName
lastName
email
address {
street
cityTown
}
}
}
}
}
}