> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Extending the core data model via GraphQL

> Learn how to create custom data models that extend the Cognite core data model using the Data modeling language extension for GraphQL.

Cognite's [core data model](/cdf/dm/dm_reference/dm_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)](/cdf/dm/dm_graphql/dm_data_modeling_language) 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.

To include the [CogniteSchedulable](/cdf/dm/dm_reference/dm_core_data_model#schedulable-props) feature from the core data model in your custom data model:

<Steps>
  <Step title="Copy the type definition">
    Copy the type definition from the core data model to your custom data model:

    ```graphql wrap showLineNumbers theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    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
    }
    ```
  </Step>

  <Step title="Add the import directive">
    Specify which data model you want to import the **view definition** from. Use the `@import` directive to import a view definition from another data model. The `dataModel` argument of the `@import` directive is used to specify which data model you are importing the view definition from. When you publish a type with the `@import` directive your current data model will be updated to include the definition of the view as it is defined in the source data model, as opposed to defining a similar but separate view definition in your current data model.

    <Note>
      A view definition cannot contain both an `@import` directive with a dataModel argument and a `@view` directive at the same time as this can create referencial conflicts when importing the view definition. You need to remove any `@view` directives from the view definition when you add `@import` as described above or you will not be able to publish the updated model.
    </Note>

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

    ```graphql wrap {18-25} showLineNumbers theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    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
    }
    ```

    <Note>
      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](/cdf/dm/dm_reference/dm_core_data_model#asset) won't work in your custom data model.
    </Note>
  </Step>
</Steps>

## Resolve transitive view dependencies

When you import a type from another data model, you must also import all the views it depends on.

To import a "Pump" view that has a direct relation to a "Location" view:

<Steps>
  <Step title="Add the type definition for Pump">
    Add the type definition for "Location" to your data model:

    ```graphql wrap showLineNumbers theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    type Pump
      @import(
        dataModel: {
          externalId: "my-custom-datamodel"
          version: "v1"
          space: "my-custom-space"
        }
      ) {
      name: String
      location: Location
    }
    ```
  </Step>

  <Step title="Import the dependent Location type">
    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":

    ```graphql wrap {14-19} showLineNumbers theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    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
    }
    ```
  </Step>
</Steps>

## Extend imported views

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

To extend the [CogniteAsset](/cdf/dm/dm_reference/dm_core_data_model#asset) concept from the core data model with a new `department` field:

<Steps>
  <Step title="Import CogniteAsset into your data model">
    Import [CogniteAsset](/cdf/dm/dm_reference/dm_core_data_model#asset) into your data model:

    ```graphql wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    type CogniteAsset implements CogniteVisualizable & CogniteDescribable & CogniteSourceable
        @view(space: "cdf_cdm", version: "v1")
        @import {
        # ... omitted CogniteAsset fields
    }
    ```
  </Step>

  <Step title="Define a custom type that implements CogniteAsset">
    Define a `CustomCogniteAsset` type that implements the [CogniteAsset](/cdf/dm/dm_reference/dm_core_data_model#asset) type:

    ```graphql wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
    type CustomCogniteAsset implements CogniteAsset & CogniteVisualizable & CogniteDescribable & CogniteSourceable {
        # ... 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` and the `@view` 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.
  </Step>
</Steps>

## 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`:

```graphql wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
type CustomCogniteAsset implements CogniteAsset & CogniteVisualizable & CogniteDescribable & CogniteSourceable {
  # ... 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:

```graphql wrap theme={"languages":{"custom":["/_languages/kuiper.json","../_languages/kuiper.json"]}}
type CustomCogniteAsset implements CogniteAsset & CogniteVisualizable & CogniteDescribable & CogniteSourceable {
  # ... omitted CogniteAsset fields
  parent: CustomCogniteAsset @mapping(property: "assetHierarchy_parent")
}
```

<Note>
  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](/cdf/dm/dm_reference/dm_core_data_model#equipment) because [CogniteEquipment](/cdf/dm/dm_reference/dm_core_data_model#equipment) doesn't extend [CogniteAsset](/cdf/dm/dm_reference/dm_core_data_model#asset).
</Note>
