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).
Types
Types are the basic building block of your data model and represent use-case specific concepts. Each type is associated with one or more properties which are each associated with another type. Below is a simple type definition in DML modeling an Equipment type with two properties: title and pages:Extending types via inheritance
Using GraphQL inheritance rules, you can create types that extend parent types and inherit all their properties.- Define a type as an interface to make it extendable.
- Use the
implementskeyword to extend this base type from another type. - Extend multiple interfaces by separating them with an ampersand (
&).
In most implementations of the GraphQL Schema Definition Language, interfaces are treated differently from types; they cannot be queried directly and serve only as blueprints to be implemented by other types.In DML, interfaces function as both types and interfaces. This means that when you change a type to an interface, the only functional difference is that it can now serve as a parent type for others. You can still query the interface via the CDF APIs as if it were still a standalone type in your data model.
Equipment) is implemented by the Pipe type, which inherits all parent properties and adds specific properties relevant only to the child type.
There are some caveats with fields that are imported from inheritance, learn more in the advanced section.
Properties
A type consists of a collection of properties. Each property can be ascalar, an enum, or a reference to a custom type. When a property references a custom type, it represents a relation between instances in your data model.
List properties
By default a property can only contain a single value:[]) around the type of the property:
Limiting number of values on list properties
By default list properties can have maximum of between 100 and 1000 values depending on the property type. To override the default maximum values on a list property, use the@limits directive:
Scalar properties
Scalar properties represent primitive data.| DML type name | DMS name | Description |
|---|---|---|
String | text | |
Int or Int32 | int32 | 32-bit integer number |
Int64 | int64 | 64-bit integer number |
Float or Float64 | float64 | 64-bit number encoded in IEEE 754 |
Float32 | float32 | 32-bit number encoded in IEEE 754 |
Timestamp | timestamp | Timestamp encoded in ISO 8601 |
JSONObject | json | JSON encoded data |
Date | date | Date encoded in ISO 8601, but without time |
Boolean | boolean |
Enum properties
Enum properties are special scalars that must match one of several predefined, distinct values. To create one, declare an enum and then use that enum as the type of another property:CDF resource type properties
Properties can also reference non-data-modeling resource types in CDF. The value of these properties is a string reference to the external ID of the underlying resource.| GraphQL type | CDF resource |
|---|---|
| File | files |
| TimeSeries | timeseries |
| Sequence | sequences |
Relation properties
Relations allow types to reference other types, forming connections within your data model. These can point to single or multiple target instances. You create relation properties in DML by defining a property that uses a custom type as its type:- Direct relations: A container property storing a reference to another node.
- Edges: A connection property that can be used to describe one-to-many or many-to-many relationships.
- Reverse direct relation: A connection property representing a direct relation in another type going in the opposite direction.
Direct relations
A relation with a single target instance defaults to a direct relation:@directRelation directive. Without this, list property will default to being modelled as an edge:
Reverse direct relations
A reverse direct relation looks “backward” through an existing direct relation on the target type. You must specify thethroughProperty on the target type for the graph traversal.
Edges
Since single-target relations default to direct relations, add the@relation directive to define a single-target edge relation:
@relation directive is necessary to model it as an edge:
Properties on edges
Edges can possess their own properties. To define these on an edge relation, create a type annotated with the@edge directive and link it using edgeSource in the @relation directive:
Overriding edge type
The edge type used to identify an instance of an edge defaults to{your_typename}.{your_fieldname}. However, you can override this behavior and manually specify the edge type using the type field within the @relation directive.
Overriding edge direction
The relational direction for edges defined in DML is OUTWARDS by default. To create a relation that points inwards (referencing incoming edges), add thedirection argument to INWARDS on the @relation directive.
Descriptions
GraphQL descriptions are supported and will be converted to the corresponding description property on view, container and property definitions. To set thename of a view, container, or field, start a line in the description with @name followed by the name value.
Example of GraphQL descriptions:
Specification of directives
The following is a list of the directive definitions, with descriptions.Advanced: Types and their relation to DMS views and containers
Types in the DML data model are abstractions of DMS schema resources (views, containers, and data models). When you publish a DML data model in your CDF project, it’s persisted in DMS as a collection of schema objects (containers, views, and data models). Similarly, when you open an existing data model in DML, the DML schema is regenerated from the published DMS schema objects.Containers and views
Each type in a DML data model has an equivalent view and container. The identifiers for these resources are determined by the following rules: Container identification (by space and external ID):- External ID: Uses the
@containerdirective’s external ID if present, otherwise defaults to the type name. - Space: Uses the
@containerdirective’s space if present, otherwise defaults to the data model’s space.
- External ID: Uses the
@viewdirective’s external ID if present, otherwise defaults to the type name. - Space: Uses the
@viewdirective’s space if present, otherwise defaults to the data model’s space. - Version: Uses the
@viewdirective’s version if present, otherwise generates a version identifier based on the type definition (ensuring any changes to the type definition result in a new view version).
View and container properties
Once a type has been mapped to a view and container, its properties are also mapped to equivalent view and container properties. Each type property always has an equivalent view property in the view mapped to the type. However, which container property the view property maps to is determined by the following rules (in order of precedence):- Explicit mapping: If the type property has a
@mappingdirective, the directive determines which container property to use. - Inherited mapping: If the property is inherited from a parent type, the view property maps to the same container property as the equivalent property in the parent type.
- Default mapping: Otherwise, the view property maps to a container property with the same name in the container mapped to the type.
When you use the
@mapping directive, the system doesn’t auto-create the referenced container property if it doesn’t exist. Only use @mapping to reference container properties that already exist.Example DML to DMS mapping
- View: Created with external ID
Equipmentin the data model’s space (no@viewdirective, so it uses the type name) - Container: Created with external ID
Equipmentin the data model’s space (no@containerdirective, so it uses the type name) - Property
name:- View property
namein theEquipmentview - Maps to container property
namein theEquipmentcontainer (no@mappingdirective and not inherited, so a new container property is created with the same name)
- View property
- View: Created with external ID
Valve2in the data model’s space (explicitly set via@viewdirective) - Container: Created with external ID
Valvein the data model’s space (no@containerdirective, so it uses the type name) - Property
name:- View property
namein theValve2view - Maps to container property
namein theEquipmentcontainer (inherited from the parentEquipmentinterface, so it reuses the same container property as the parent)
- View property
- Property
diameter:- View property
diameterin theValve2view - Maps to container property
diameterin theValvecontainer (no@mappingdirective and not inherited, so a new container property is created)
- View property
- Property
material:- View property
materialin theValve2view - Maps to container property
materialin theValvecontainer (no@mappingdirective and not inherited, so a new container property is created)
- View property
The
Valve type’s name property references the Equipment container rather than its own Valve container. This is because inherited properties always map to the same container property as their parent type.Spaces and naming collisions
When you create multiple data models in the same space with identical type names, they will interfere with each other and cause errors. Consider this scenario where you have two data models in the same space: Data model A:- Use one data model per space - This eliminates the possibility of collisions.
- Use unique type names - If you need multiple data models in the same space, ensure all type names are unique across models.