The data modeling language extension for GraphQL
This article describes the current capabilities of the Data modeling language extension for GraphQL (DML).
The DML extension lets you control both the data model-centric, and the view-centric —the solution data model—management of a Data Modeling Service (DMS) based schema.
The data modeling REST API (DMS) in combination with the Cognite Python SDK offers more power and flexibility than the DML extension. They're the preferred tools for managing industrial knowledge graphs in Cognite Data Fusion (CDF).
Basics
The data model format is in the GraphQL Schema Definition Language. Each data model has many types, consisting of properties, each with a specified type.
Each type can contain properties that reference other types, forming a relationship. You can also specify the propertiess as a list of references to nodes of other types.
Use !
to indicate that a field is required and that each instance of the template must contain the value.
To add comments, enter "comment"
above the field/type definition.
This example is a simple data model for movies:
type Equipment {
"Unique identifier for the equipment"
id: int!
"name of the piece of equipment"
name: String!
"the parts included to build this equipment"
parts: [Part]
"the documents describing use and maintenance for the equipment"
documentation: [Document]
}
type Part {
id: int!
name: String!
documentation: [Document]
}
type Document {
id: int!
name: String!
source: String!
"the equipment this document describes"
equipment: Equipment
"the parts this document describes"
parts: [Part]
}
Where:
Equipment
type has the propertiesid
, andname
properties.-
id
must be anInteger
type, and must exist on all nodes ofEquipment
.name
must be aString
type, and must exist on all nodes ofEquipment
.
Equipment
type has aparts
relationship to a list/array of one or morePart
s.Equipment
type has adocumentation
relationship to a list/array of one or moreDocument
s.Part
has the propertiesid
andname
,id
must be anInteger
type, and must exist on all nodes ofPart
.name
must be aString
type, and must exist on all nodes ofPart
.
Part
has adocumentation
relationship to a list/array of one or moreDocument
s.Document
type has the propertiesid
,name
, andFile
.id
must be anInteger
type, and must exist on all nodes ofDocument
.name
must be aString
type, and must exist on all nodes ofDocument
.source
must be aString
type, and must exist on all nodes ofDocument
.
Document
has aequipment
relationship to a single (piece of)Equipment
.Equipment.name
has a comment/description (name of the piece of equipment).
Types and Interfaces
An object type in GraphQL is defined by using the keyword type, for example type Equipment
defines an object type in GraphQL
called Equipment
.
An interface type in GraphQL is defined by using the keyword interface, for example interface Equipment
.
From a data querying or population perspective, there are no difference between a type being an object or interface. However, only interface can be extended / implemented upon.
EquipmentInterface
and EquipmentObject
will here have the same query capabilities:
interface EquipmentInterface {
name: String
}
type EquipmentObject {
name: String
}
In our DML, an object or interface type represents a view by default. This is the same as specifying the @view
directive.
When a @view directive is not specified, the view version will be managed by the GraphQL service. When a new
view version is needed due to breaking changes, the data model version will also have to be changed.
View versions can also be overriden by directives.
We call types having a '@view' directive for view types. A view type can extend from other view types, allowing for graphql inheritance, more in the next section.
Extending types via inheritance
We rely on the inheritance rules as defined by GraphQL, so to extend another view type, that base view type has to be an interface.
A view type can be extendable via inheritance by defining the type to be an interface. A view type can then extend the base type by
using implements
. You can also extend multiple interfaces by separating them with &
.
This is an example of a view extending another view:
interface Common {
name: String
}
type Equipment implements Common {
name: String
}
There are some caveats with fields that are imported from inheritance, learn more in the advanced section.