Appearance
2. Creating a Data Schema
Using our Data Development Kit (DDK), you can configure the data schema for your project. This allows you to build one or many data schemas to connect all the data required for your use case and leverage this across any application.
What You'll Learn
- Create a DDK server and configure database connections
- Define schema objects (
SimSettingsandSimOutcome) with fields and constraints - Establish relationships between objects using foreign keys
- Configure resolvers and workflow triggers
- Build, deploy, and migrate your schema
- Test your schema using GraphiQL
Before starting, consider the application you want to design and what data needs to be displayed on the front end. This will help you determine which schemas, objects, and fields you need. The following instructions walk you through setting up a data schema for a traffic network simulation.
2.1 Creating a Server
Click on the New Server button to create a server. This server acts as your data schema and is responsible for storing the APIs and resolvers required to manage your data schema effectively.

Fill out the following information for the Server details section:
- Server name: Must be all lowercase with no numbers or spaces (e.g.,
transport) - Port: A minimum four-digit number (e.g.,
1234)

Click Next and fill out the following information for the Create new schema section:
- Schema Name: Must be all lowercase with no numbers or spaces (e.g.,
transportschema). You can have multiple schemas per server to separate your data objects.

Click Next and fill out the following information for the Configure databases section:
- Alias:
postgres - Port:
5432 - Username:
postgres - Password:
postgres - Database name:
postgres - Schema name:
public
After filling in all the required fields, click on the Next button.

In the Configure Redis step, you can enable or disable Redis based on your needs. Finally, click on Create to create the DDK server.

Custom code options
Want to see what more complex schemas look like? You can use the code editor tool to copy in some sample schema templates available at this link: Data Schema Code Templates
Alternatively, if you're familiar with GraphQL and have your own schema in mind you can write this out using the custom code editor.
The server has been successfully created, as shown below.

2.2 Configuring Your Schema
Now that the schema has been created, you can define objects relevant to your project. The following instructions will allow you to recreate the OR Demo Project and guide you through the steps required for future projects.
You can define fields in the Types tab. To add each field, simply drag it into the visualiser.
Object
An object is a definition of data records in the system. We are scaffolding the different pieces of data required to build an end-to-end application.
Creating the SimSettings Object
Define the object that will set the inputs for your simulation. We'll call this object SimSettings.
SimSettings
This object will represent setting the geographical location required to simulate a traffic network. The fields required to set the geographical location are: longitude, latitude, and radius.

Add a new Object Field, then change the object name to SimSettings by clicking the three-dot menu and selecting Edit Metadata.

The id field is created by default. To configure it:
- Click the
idfield to open its configuration panel - In the DataType tab, mark the field as Required
- Under Constraints, enable Primary Key
- Click Update to save the changes

INFO
This id field is a primary key which acts as a unique identifier for your SimSettings object.
Every object defined in your schema mirrors a table in a database. Think of defining your schema as structuring relational database tables. In this step, you're defining a SimSettings table with a unique identifier column called id.
With the SimSettings object selected, click the + icon to add a new field. Set the Name to longitude. In the DataType tab, click the Field required checkbox and select Float from the Data type dropdown. Click Update.

INFO
Setting a field as Field required is a way of saying this field must have a data value in its database cell. In this example, longitude must have a float (decimal) value in every row entry in the table.
With the SimSettings object selected, click the + icon to add a new field. Set the Name to latitude. In the DataType tab, click the Field required checkbox and select Float from the Data type dropdown. Click Update.

With the SimSettings object selected, click the + icon to add a new field. Set the Name to radius. In the DataType tab, click the Field required checkbox and select Int from the Data type dropdown. Set the default value to 10. Click Update.

SimSettings
In this example, the longitude and latitude values represent coordinates, and the radius captures the map radius area from that coordinate location.
SimSettings Fields Summary
| Field Name | Data Type | Required | Constraints | Default Value |
|---|---|---|---|---|
id | ID | Yes | Primary Key | - |
longitude | Float | Yes | - | - |
latitude | Float | Yes | - | - |
radius | Int | Yes | - | 10 |
Creating the SimOutcome Object
Define our second object to store the outcome of your simulation. We'll call this object SimOutcome. Drag Object into the visualiser to create it.

Change the object name to SimOutcome.

SimOutcome
This object will represent and store the outcomes of your traffic simulation after it's executed. The fields that the simulation will output are:
result: The actual result from the simulation. This stores a mapping of all the vehicle coordinates at a certain time.dtTimestamp: The date-timestamp of a simulation result.simSettingsId: An id that matches aSimSettingsrecord. This is a one-to-one relationship - eachSimSettingstable matches to aSimOutcometable.
The id field is created by default. To configure it:
- Click the
idfield to open its configuration panel - In the DataType tab, mark the field as Required
- Under Constraints, enable Primary Key (this acts as a unique identifier for your
SimOutcomeobject) - Click Update to save the changes

With the SimOutcome object selected, click the + icon to add a new field. Change name to dtTimestamp. In the DataType tab, click the Field required checkbox and select Int from the Data type dropdown. Click Update.

INFO
dtTimestamp is a short-hand for date-timestamp. It will store the date timestamp for a set of simulation results. This field is important to be able to view the movement of your traffic network in chronological order.
With the SimOutcome object selected, click the + icon to add a new field. Change name to result. In the DataType tab, click the Field required checkbox and select String from the Data type dropdown. Click Update.

With the SimOutcome object selected, click the + icon to add a new field. Change name to simSettingsId. In the DataType tab, click the Field required checkbox and select ID from the Data type dropdown. Click Update.

This completes the SimOutcome object.
SimOutcome Fields Summary
| Field Name | Data Type | Required | Constraints | Default Value |
|---|---|---|---|---|
id | ID | Yes | Primary Key | - |
dtTimestamp | Int | Yes | - | - |
result | String | Yes | - | - |
simSettingsId | ID | Yes | Unique | - |
SimOutcome
This object is responsible for storing the results of each simulation execution. In combination with the result and dtTimestamp fields, we will leverage this object to visualise the results on a map.
Creating the Relationship
Now we'll create a relationship to link our two objects together.
- Click back to the SimSettings object and add a new field by clicking the + icon.
- Click the new field to open its settings.
- Change the name to
SimOutcomeand click Update. - Go to the DataType tab and configure the following:
- Mark the field as Required
- From the Type dropdown, select Existing Object and set the DataType to
SimOutcome - Set Mapping to
One-to-One - Set the Foreign Key to
simSettingsId - Set the Foreign Key Reference to
id
- Click Update to save the changes.

Foreign key mappings
A foreign key is a database concept that shows the relationship between 2 objects/tables. In our SimOutcome field, we are essentially saying "grab the simSettingsId field from one table and link it to the primary key (id) of the other table".
From a high-level view, this relationship means that every settings input that is passed into a simulation is linked to a specific outcome.
After clicking Update, you should see a link between the two objects as shown below.

You can also hover over the link to view more details.

This completes the SimSettings object.
Configuring Resolvers
- In the
SimSettingsobject, click the Configure icon at the bottom of the node to open the configuration panel.

- In the Basic tab, ensure all options are checked: Create, Read, Update, Delete.
Resolver
A resolver is essentially a function in a DDK server on how to fetch/modify data of an object.
Linking it to a database table, there are four default resolvers:
- create: Creates a new row entry in a database table with data for an object.
- read: Reads/fetches a row entry or list of entries from a database table for an object.
- update: Updates specific fields in a row entry of a database table for an object.
- delete: Deletes a row from a database table for an object.
- Go to the Advanced tab, enable Allow workflow trigger operations, and click Update.

Trigger
A trigger is a link to the Modelling Development Kit (MDK) that allows MDK workflows (ie. our traffic simulation) to be executed via an object default resolver.
In other words, we are enabling the option where if a default resolver is executed, it will trigger a deployed simulation workflow from the MDK.
Your final schema should look like this:

ORA in the DDK
You can use our Optimal Reality Assistant (ORA) in the DDK. Click the AI icon on the right to install ORA.
ORA allows you to describe your schema using natural language, and it will generate the code for you.

You can then review the code and publish. We won't use ORA in this walkthrough since we need a specific schema setup, but feel free to explore this feature later.

A Note About Loading Data
This Traffic Simulation example doesn't require pre-loaded data since all data is generated through the simulation. However, here are the options available for loading data when needed.
To attach data, you'll need to install Experiment Manager first (this happens automatically when you open the MDK for the first time).
On a schema object, click the three-dot menu on the right side to access these options:
- Mock Data Generation: Users can generate mock data for any object in the schema. This data is automatically structured to match the object's fields, so no mapping is required.
- Data Attachment: Users can attach data to objects by importing CSV files from their local machine or from URLs. The system provides a wizard to map source fields to target object fields, with options to match exactly or skip fields.

Custom code options
To import data from a file you'll need to use VS Code to upload the relevant file to your local instance. You can access that here: https://web.core.optimalreality.com/code
2.3 Deploying Your Schema
Now that you've configured your schema in section 2.2, it's time to deploy it.
1. Click the Regenerate button in the top center of the screen and wait for it to be successful.

Regeneration
Regeneration is a concept that checks and validates your schema structure.

Build and Deploy
2. Click the Build button (hammer icon) to build your DDK server and wait for it to be successful.
Build
Build means that we are packaging your entire DDK server (with your schema) into an asset. This asset is called an image. This image will become crucial in deploying your schema into the local environment. In this process, all the APIs required for the front-end, back-end, and modelling are all auto-generated.

3. Go back to the Nexus and within the Container registry panel on the left side, click on the three dots in the transport (or your custom named server) node and select Configure Deployment to confirm/validate the fields.

You can also click the three-dot menu on the Transport node in the Visualiser and select Configure Deployment.

Set the Version Tag to latest, then click Next and Save.

INFO
These wizards are prefilled with sensitive defaults and do not need to be changed.
Once complete, go back to the Container registry panel and repeat the same process for the postgres node.


Configuration
This process is setting and saving the configuration of the images. These configurations are displayed by default. We have two images:
- our DDK
transportserver, and - the
postgresdatabase that we configured in section 2.1.
4. Select the Deploy button in the top center.

Select the two images in the pop up.

Click Next, then click Deploy.

5. Wait for your transport node and postgres node to become healthy (green) in Nexus.

Troubleshooting
If, after deployment, the postgres and transport nodes are still not green (healthy), click on the Logs tab on the right panel, check the logs to find the cause of the issue, and if the problem persists, contact OR support.

Deployment
Deploying these images into the local environment means we want our DDK transport and postgres microservices to run in the environment.
There's a link between transport and postgres to indicate a database dependency.
Once both microservices are running healthily in Nexus, go back to the DDK.
Creating Migrations
Back in the DDK, we need to migrate the schema to make it available:
6. Click the Migrate button at the top center of your server (e.g. transport).
7. Click on + Create migration. Then Click on Create. This may take a few minutes.

Migrations
Data migrations move data between systems, formats, or storage solutions on deployed databases. They ensure integrity, compatibility, and minimal downtime while upgrading, consolidating, or transitioning applications and databases. This involves extraction, transformation, validation, and loading (ETL) processes.
8. Once the migration is created, you'll see the View All Migrations panel (you can also access this panel by clicking the Migrate button and selecting View All). Select latest from the left panel and click the Apply latest button, then wait for it to complete successfully.
INFO
This makes the tables for the data schema, allowing your database to be migrated to the appropriate version of the DDK server.

🎉 Once migration apply is complete, you continue to the Modelling Development Kit!
Follow the instructions in: Building and Configuring Workflows
For more advanced tutorials on GraphiQL and low-code schema development, see below.
2.4 GraphiQL
In the DDK, there is a sub-tool called GraphiQL View. This is the built-in GraphQL interface that allows you to test GraphQL queries and resolvers. You can explore the schema documentation to see the types, objects, and resolvers in your server data schema. Think of it as Postman, but for GraphQL.
To access GraphiQL:
Click the GraphiQL View icon in the second left sidebar while inside the DDK.

Schema Documentation
Click on the top left book icon to view the Docs.
This allows you to explore the schema for this GraphQL server. You can discover different types and their fields, as well as available query, mutation, and subscription resolvers, including their arguments and return types. Learn more about the type system here: Schemas and Types | GraphQL

Query Editor and Executor
In the middle pane, you can write GraphQL operations for queries and mutations to execute resolvers in the server.
For example, you may wish to send a mutation to create a sim settings object:
graphql
mutation createSimSettings {
createSimSettings(
id: "id_1"
longitude: 144.946457
latitude: -37.840935
radius: 10
) {
id
longitude
latitude
radius
}
}Copy the operation above and execute it using the play icon (or Cmd/Ctrl + Enter on selected cursor).

Then for example, you may wish to query for the current sim settings objects in the DB:
graphql
query getSimSettingsList {
getSimSettingsList {
id
longitude
latitude
radius
}
}Copy the operation above and execute it using the play icon (or Cmd/Ctrl + Enter on selected cursor).

This is a useful tool for testing your auto-generated GraphQL schema and resolvers before integrating with MDK workflows or FDK components.
2.5 Low Code Options
Low Code Options
To view and edit the code directly, click the Code View button </> Code to see the generated code. You can edit or add objects through here, but the schema must follow a specific format to save successfully.


Custom Code Options
To import a schema you've created elsewhere, or write one from scratch, click the Code View button </> Code in the top center-right of the panel. Rather than configuring options as we did in section 2.2, you can copy over or write the schema directly in code.
Example from this tutorial:
graphql
type SimSettings @required(type: "CREATE, READ, UPDATE, DELETE", table: "true", trigger: "true") {
id: ID! @constraint(type: "primarykey")
longitude: Float!
latitude: Float!
radius: Int! @constraint(type: "default", value: "10")
simOutcome: SimOutcome! @mapping(type: "one2one", foreignKey: "simSettingsId", foreignKeyReference: "id")
}
type SimOutcome @required(type: "CREATE, READ, UPDATE, DELETE", table: "true") {
id: ID! @constraint(type: "primarykey")
dtTimestamp: Int!
result: String!
simSettingsId: ID! @constraint(type: "unique")
}Next Steps
Now that your data schema is configured and deployed, you're ready to build workflows in the MDK.
