Pāriet uz galveno saturu

Extending the core data model via GraphQL

Cognite's core data model offers standardized building blocks for industrial data, forming the basis for more specialized models. This article outlines how to use the Data modeling language extension for GraphQL (DML) to create a custom data model that extends the core data model.

Import types from the core data model

By default, new custom data models don't have any type definitions. Before extending the core data model, you must import the type definitions you need from the core data model into the custom data model.

For example, to include the CogniteSchedulable feature from the core data model in your custom data model:

  1. Copy the type definition from the core data model to your custom data model:

    interface CogniteSchedulable
    @container(
    indexes: [
    { identifier: "startTime", fields: ["startTime"], cursorable: true }
    { identifier: "endTime", fields: ["endTime"], cursorable: true }
    {
    identifier: "scheduledStartTime"
    fields: ["scheduledStartTime"]
    cursorable: true
    }
    {
    identifier: "scheduledEndTime"
    fields: ["scheduledEndTime"]
    cursorable: true
    }
    ]
    ) {
    startTime: Timestamp
    endTime: Timestamp
    scheduledStartTime: Timestamp
    scheduledEndTime: Timestamp
    }
  2. Specify which data model you want to import the view definition from. Use the @import directive to import the type definition from another type and to decide which data model and version to import from.

    For example, to import the view from the core data model instead of creating a new view with the same schema in the custom data model:

    interface CogniteSchedulable
    @container(
    indexes: [
    { identifier: "startTime", fields: ["startTime"], cursorable: true }
    { identifier: "endTime", fields: ["endTime"], cursorable: true }
    {
    identifier: "scheduledStartTime"
    fields: ["scheduledStartTime"]
    cursorable: true
    }
    {
    identifier: "scheduledEndTime"
    fields: ["scheduledEndTime"]
    cursorable: true
    }
    ]
    )
    @import(
    dataModel: { externalId: "CogniteCore", version: "v1", space: "cdf_cdm" }
    ) {
    startTime: Timestamp
    endTime: Timestamp
    scheduledStartTime: Timestamp
    scheduledEndTime: Timestamp
    }
piezīme

If you copy the type definition without the @import directive and publish the data model, you create a new view and container in your custom data model space independent from the core data model. You won't be able to access the data of the views stored in the core data model from your custom data model. Also, functionality such as path materialization of CogniteAsset won't work in your custom data model.

Resolve transitive view dependencies

When you import a type from another data model, you must also import all the views it depends on. For example, to import a "Pump" view that has a direct relation to a "Location" view:

  1. Add the type definition for "Location" to your data model:

    type Pump
    @import(
    dataModel: {
    externalId: "my-custom-datamodel"
    version: "v1"
    space: "my-custom-space"
    }
    ) {
    name: String
    location: Location
    }
  2. The data model won't validate since the "Location" type isn't defined yet. To define it, you need to import the "Location" view in the same way you imported "Pump":

    type Pump
    @import(
    dataModel: {
    externalId: "imaginary-datamodel"
    version: "v1"
    space: "imaginary-space"
    }
    ) {
    name: String
    location: Location
    }

    type Location
    @import(
    dataModel: {
    externalId: "my-custom-datamodel"
    version: "v1"
    space: "my-custom-datamodel"
    }
    ) {
    name: String
    }

Extend imported views

When you've imported the necessary types from the core data model, you can extend them to match your needs.

This example extends the CogniteAsset concept from the core data model with a new department field:

  1. Import CogniteAsset into your data model:

    type CogniteAsset implements CogniteVisualizable & CogniteDescribable & CogniteSourceable
    @view(space: "cdf_cdm", version: "v1")
    @import {
    # ... omitted CogniteAsset fields
    }
  2. Define a CustomCogniteAsset type that implements the CogniteAsset type:

    type CustomCogniteAsset implements CogniteAsset & CogniteVisualizable & CogniteDescribable & CogniteSourceable
    @view(space: "cdf_cdm", version: "v1") {
    # ... omitted CogniteAsset fields
    department: String
    }

    interface CogniteAsset implements CogniteVisualizable & CogniteDescribable & CogniteSourceable
    @view(space: "cdf_cdm", version: "v1")
    @import {
    # ... omitted CogniteAsset fields
    }

In the example above:

  • We removed the @import from CustomCogniteAsset because the type is owned by the custom data model and not imported from the core data model like the CogniteAsset type.
  • We changed CogniteAsset to be an interface instead of a type. The GraphQL specification requires this, and it has no impact on the functionality of the imported CogniteAsset type.
  • We included all the fields from the CogniteAsset on the CustomCogniteAsset. The GraphQL specification requires that all fields of the base interface are included when implementing it in another type.

Override types for edges and direct relations

When you have defined an extension to an existing type, you typically want any direct relation fields that reference the base type to reference the extension type instead.

This example defines an extension of CogniteAsset called CustomCogniteAsset:

type CustomCogniteAsset implements CogniteAsset & CogniteVisualizable & CogniteDescribable & CogniteSourceable
@view(space: "cdf_cdm", version: "v1")
@import {
# ... omitted CogniteAsset fields
parent: CogniteAsset @mapping(property: "assetHierarchy_parent")
}

The parent direct relation still references the base type (CogniteAsset). If you query for data on the parent direct relation via CustomCogniteAsset, you won't be able to access the data of the department field since it only exists in CustomCogniteAsset.

To solve this issue, you need to manually override the type of the parent direct relation on the CustomCogniteAsset to reference the CustomCogniteAsset type instead of the base type:

type CustomCogniteAsset implements CogniteAsset & CogniteVisualizable & CogniteDescribable & CogniteSourceable
@view(space: "cdf_cdm", version: "v1")
@import {
# ... omitted CogniteAsset fields
parent: CustomCogniteAsset @mapping(property: "assetHierarchy_parent")
}
piezīme

You can only change the type of a field from the base type like this if you're overriding the existing type with a type that implements it. For example, you can't change the parent field type to CogniteEquipment because CogniteEquipment doesn't extend CogniteAsset.