cognite-create 0.2.15 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/templates/.cursor/mcp.json +4 -4
- package/templates/.cursor/rules/core-cdf-apis.mdc +1525 -0
- package/templates/.cursor/rules/datamodelling.mdc +2023 -0
- package/templates/.cursor/rules/development.mdc +90 -0
- package/templates/.cursor/rules/general.mdc +2 -0
- package/templates/.cursor/rules/requirements-gathering.mdc +24 -0
- package/templates/.env.example +11 -0
|
@@ -0,0 +1,2023 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: true
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Cognite Data Modeling SDK Guide
|
|
6
|
+
|
|
7
|
+
## Introduction
|
|
8
|
+
|
|
9
|
+
The Cognite Data Modeling service (DMS) enables you to build, populate, and query flexible data models in Cognite Data Fusion (CDF). This SDK provides JavaScript/TypeScript APIs to work with the core components of data modeling: **Instances** (nodes and edges), **Views**, **Containers**, and **Data Models**. Together, these components allow you to create an industrial knowledge graph that represents your assets, their relationships, and associated data in a structured, scalable way.
|
|
10
|
+
|
|
11
|
+
Data modeling in CDF follows a property graph approach where:
|
|
12
|
+
|
|
13
|
+
- **Nodes** represent entities (like assets, equipment, or documents)
|
|
14
|
+
- **Edges** represent relationships between nodes
|
|
15
|
+
- **Properties** store the actual data values
|
|
16
|
+
- **Views** define the schema and how data is accessed
|
|
17
|
+
- **Containers** handle the physical storage and indexing
|
|
18
|
+
- **Data Models** group views together for specific use cases
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
To use the data modeling APIs, install the Cognite SDK:
|
|
23
|
+
|
|
24
|
+
Using npm:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @cognite/sdk --save
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Using yarn:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
yarn add @cognite/sdk
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Initialization
|
|
37
|
+
|
|
38
|
+
Initialize the CogniteClient with your project details and authentication:
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
import { CogniteClient } from "@cognite/sdk";
|
|
42
|
+
|
|
43
|
+
const client = new CogniteClient({
|
|
44
|
+
appId: "YOUR_APP_NAME",
|
|
45
|
+
project: "YOUR_PROJECT_NAME",
|
|
46
|
+
oidcTokenProvider: async () => {
|
|
47
|
+
return "YOUR_OIDC_ACCESS_TOKEN";
|
|
48
|
+
},
|
|
49
|
+
baseUrl: "https://api.cognitedata.com", // Optional
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Core Concepts
|
|
54
|
+
|
|
55
|
+
### Spaces
|
|
56
|
+
|
|
57
|
+
Spaces are logical groupings that help organize and secure data model components. Each container, view, data model, and instance belongs to a specific space. Spaces provide:
|
|
58
|
+
|
|
59
|
+
- **Organization**: Group related data model components together
|
|
60
|
+
- **Access Control**: Manage permissions at the space level
|
|
61
|
+
- **Isolation**: Separate different projects or domains
|
|
62
|
+
- **Namespacing**: Avoid naming conflicts between components
|
|
63
|
+
|
|
64
|
+
CDF provides several system spaces:
|
|
65
|
+
|
|
66
|
+
- `cdf_cdm`: Contains the Cognite core data model
|
|
67
|
+
- `cdf_cdm_units`: Contains unit definitions
|
|
68
|
+
- `cdf_extraction_extensions`: Used by Cognite extractors
|
|
69
|
+
|
|
70
|
+
Reserved space names that cannot be used:
|
|
71
|
+
|
|
72
|
+
- `space`, `cdf`, `dms`, `pg3`, `shared`, `system`, `node`, `edge`
|
|
73
|
+
|
|
74
|
+
### Property Graph Model
|
|
75
|
+
|
|
76
|
+
CDF uses a property graph where:
|
|
77
|
+
|
|
78
|
+
- **Nodes** are vertices in the graph with properties
|
|
79
|
+
- **Edges** are directed connections between nodes with their own properties
|
|
80
|
+
- **Direct Relations** are properties that reference other nodes (stored on the node itself)
|
|
81
|
+
- **Types** categorize nodes and edges using direct relations
|
|
82
|
+
|
|
83
|
+
### Schema Components Hierarchy
|
|
84
|
+
|
|
85
|
+
1. **Containers**: Define physical storage with properties, constraints, and indexes
|
|
86
|
+
2. **Views**: Provide semantic layers over containers, supporting inheritance and filtering
|
|
87
|
+
3. **Data Models**: Group related views for specific use cases or applications
|
|
88
|
+
|
|
89
|
+
## Key Methods & Functions
|
|
90
|
+
|
|
91
|
+
### Spaces API
|
|
92
|
+
|
|
93
|
+
The Spaces API manages the logical groupings that organize and secure your data model components.
|
|
94
|
+
|
|
95
|
+
#### client.spaces.upsert(params)
|
|
96
|
+
|
|
97
|
+
- **Description**: Creates or updates spaces
|
|
98
|
+
- **Parameters**:
|
|
99
|
+
- `params` (SpaceCreateDefinition[], required): Array of space definitions
|
|
100
|
+
- **Return Type**: Promise<SpaceCollectionResponseV3Response>
|
|
101
|
+
- **Example**:
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
const spaces = await client.spaces.upsert([
|
|
105
|
+
{
|
|
106
|
+
space: "equipment_data",
|
|
107
|
+
name: "Equipment Data",
|
|
108
|
+
description: "Space for equipment-related data models and instances",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
space: "maintenance_ops",
|
|
112
|
+
name: "Maintenance Operations",
|
|
113
|
+
description: "Space for maintenance workflows and history",
|
|
114
|
+
},
|
|
115
|
+
]);
|
|
116
|
+
|
|
117
|
+
console.log(`Created ${spaces.items.length} spaces`);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### client.spaces.list(params?)
|
|
121
|
+
|
|
122
|
+
- **Description**: Lists spaces with optional filtering
|
|
123
|
+
- **Parameters**:
|
|
124
|
+
- `params` (Object, optional): Query parameters
|
|
125
|
+
- `includeGlobal` (boolean): Include global/system spaces
|
|
126
|
+
- `limit` (number): Maximum number of results
|
|
127
|
+
- `cursor` (string): Pagination cursor
|
|
128
|
+
- **Return Type**: CursorAndAsyncIterator<SpaceDefinition>
|
|
129
|
+
- **Example**:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
// List user-created spaces
|
|
133
|
+
const userSpaces = await client.spaces
|
|
134
|
+
.list({
|
|
135
|
+
includeGlobal: false,
|
|
136
|
+
limit: 100,
|
|
137
|
+
})
|
|
138
|
+
.autoPagingToArray();
|
|
139
|
+
|
|
140
|
+
console.log("User spaces:");
|
|
141
|
+
userSpaces.forEach((space) => {
|
|
142
|
+
console.log(`- ${space.space}: ${space.name}`);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// List all spaces including global ones
|
|
146
|
+
const allSpaces = await client.spaces
|
|
147
|
+
.list({
|
|
148
|
+
includeGlobal: true,
|
|
149
|
+
})
|
|
150
|
+
.autoPagingToArray();
|
|
151
|
+
|
|
152
|
+
console.log(`Total spaces: ${allSpaces.length}`);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### client.spaces.retrieve(params)
|
|
156
|
+
|
|
157
|
+
- **Description**: Retrieves specific spaces by ID
|
|
158
|
+
- **Parameters**:
|
|
159
|
+
- `params` (string[], required): Array of space IDs
|
|
160
|
+
- **Return Type**: Promise<SpaceCollectionResponseV3Response>
|
|
161
|
+
- **Example**:
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
const spaces = await client.spaces.retrieve([
|
|
165
|
+
"equipment_data",
|
|
166
|
+
"maintenance_ops",
|
|
167
|
+
"cdf_cdm", // Core data model space
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
spaces.items.forEach((space) => {
|
|
171
|
+
console.log(`Space: ${space.space}`);
|
|
172
|
+
console.log(` Name: ${space.name}`);
|
|
173
|
+
console.log(` Description: ${space.description}`);
|
|
174
|
+
console.log(` Is Global: ${space.isGlobal}`);
|
|
175
|
+
console.log(` Created: ${new Date(space.createdTime)}`);
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### client.spaces.delete(params)
|
|
180
|
+
|
|
181
|
+
- **Description**: Deletes spaces (and all contained data)
|
|
182
|
+
- **Parameters**:
|
|
183
|
+
- `params` (string[], required): Array of space IDs to delete
|
|
184
|
+
- **Return Type**: Promise<{ items: string[] }>
|
|
185
|
+
- **Example**:
|
|
186
|
+
|
|
187
|
+
```javascript
|
|
188
|
+
// WARNING: This deletes the space and ALL its contents
|
|
189
|
+
const result = await client.spaces.delete(["obsolete_space"]);
|
|
190
|
+
|
|
191
|
+
console.log(`Deleted spaces: ${result.items.join(", ")}`);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Important**: Deleting a space will delete all containers, views, data models, and instances within that space. This operation cannot be undone.
|
|
195
|
+
|
|
196
|
+
### Instances API
|
|
197
|
+
|
|
198
|
+
The Instances API manages nodes and edges in your property graph.
|
|
199
|
+
|
|
200
|
+
#### client.instances.upsert(params)
|
|
201
|
+
|
|
202
|
+
- **Description**: Creates or updates nodes and edges
|
|
203
|
+
- **Parameters**:
|
|
204
|
+
- `params` (NodeAndEdgeCreateCollection, required): Collection of nodes/edges to upsert
|
|
205
|
+
- **Return Type**: Promise<SlimNodeAndEdgeCollectionResponse>
|
|
206
|
+
- **Example**:
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
const result = await client.instances.upsert({
|
|
210
|
+
items: [
|
|
211
|
+
{
|
|
212
|
+
instanceType: "node",
|
|
213
|
+
externalId: "pump-001",
|
|
214
|
+
space: "industrial-assets",
|
|
215
|
+
sources: [
|
|
216
|
+
{
|
|
217
|
+
source: {
|
|
218
|
+
externalId: "Equipment",
|
|
219
|
+
space: "cdf_core",
|
|
220
|
+
type: "view",
|
|
221
|
+
version: "v1",
|
|
222
|
+
},
|
|
223
|
+
properties: {
|
|
224
|
+
name: "Water Pump 001",
|
|
225
|
+
description: "Primary cooling system pump",
|
|
226
|
+
manufacturer: "ACME Corp",
|
|
227
|
+
serialNumber: "WP-5000-001",
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
instanceType: "edge",
|
|
234
|
+
externalId: "located-in-001",
|
|
235
|
+
space: "industrial-assets",
|
|
236
|
+
type: { externalId: "locatedIn", space: "relationships" },
|
|
237
|
+
startNode: { externalId: "pump-001", space: "industrial-assets" },
|
|
238
|
+
endNode: { externalId: "facility-001", space: "industrial-assets" },
|
|
239
|
+
sources: [
|
|
240
|
+
{
|
|
241
|
+
source: {
|
|
242
|
+
externalId: "LocationRelation",
|
|
243
|
+
space: "relationships",
|
|
244
|
+
type: "view",
|
|
245
|
+
version: "v1",
|
|
246
|
+
},
|
|
247
|
+
properties: {
|
|
248
|
+
since: "2024-01-15",
|
|
249
|
+
floor: 2,
|
|
250
|
+
room: "2B",
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
autoCreateDirectRelations: true, // Auto-create missing target nodes
|
|
257
|
+
replace: false, // Merge properties instead of replacing
|
|
258
|
+
});
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### client.instances.list(params)
|
|
262
|
+
|
|
263
|
+
- **Description**: Lists instances with filtering and pagination
|
|
264
|
+
- **Parameters**:
|
|
265
|
+
- `params` (NodeOrEdgeListRequestV3, required): Query parameters
|
|
266
|
+
- **Return Type**: Promise<NodeAndEdgeCollectionResponseWithCursorV3Response>
|
|
267
|
+
- **Example**:
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
const nodes = await client.instances.list({
|
|
271
|
+
instanceType: "node",
|
|
272
|
+
sources: [
|
|
273
|
+
{
|
|
274
|
+
source: {
|
|
275
|
+
externalId: "Equipment",
|
|
276
|
+
space: "cdf_core",
|
|
277
|
+
type: "view",
|
|
278
|
+
version: "v1",
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
filter: {
|
|
283
|
+
equals: {
|
|
284
|
+
property: ["node", "space"],
|
|
285
|
+
value: "industrial-assets",
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
sort: [
|
|
289
|
+
{
|
|
290
|
+
property: ["name"],
|
|
291
|
+
direction: "ascending",
|
|
292
|
+
nullsFirst: false,
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
limit: 100,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Iterate through results
|
|
299
|
+
console.log(`Found ${nodes.items.length} equipment nodes`);
|
|
300
|
+
for (const node of nodes.items) {
|
|
301
|
+
console.log(node.externalId, node.properties);
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### client.instances.retrieve(params)
|
|
306
|
+
|
|
307
|
+
- **Description**: Retrieves specific instances by ID
|
|
308
|
+
- **Parameters**:
|
|
309
|
+
- `params` (ListOfSpaceExternalIdsRequestWithTyping, required): Items to retrieve
|
|
310
|
+
- **Return Type**: Promise<NodeAndEdgeCollectionResponseV3Response>
|
|
311
|
+
- **Example**:
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
const instances = await client.instances.retrieve({
|
|
315
|
+
sources: [
|
|
316
|
+
{
|
|
317
|
+
source: {
|
|
318
|
+
externalId: "Equipment",
|
|
319
|
+
space: "cdf_core",
|
|
320
|
+
type: "view",
|
|
321
|
+
version: "v1",
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
items: [
|
|
326
|
+
{
|
|
327
|
+
externalId: "pump-001",
|
|
328
|
+
space: "industrial-assets",
|
|
329
|
+
instanceType: "node",
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
externalId: "pump-002",
|
|
333
|
+
space: "industrial-assets",
|
|
334
|
+
instanceType: "node",
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
#### client.instances.search(params)
|
|
341
|
+
|
|
342
|
+
- **Description**: Searches instances using text queries and filters
|
|
343
|
+
- **Parameters**:
|
|
344
|
+
- `params` (NodeOrEdgeSearchRequest, required): Search parameters
|
|
345
|
+
- **Return Type**: Promise<NodeAndEdgeCollectionResponseV3Response>
|
|
346
|
+
- **Example**:
|
|
347
|
+
|
|
348
|
+
```javascript
|
|
349
|
+
const searchResults = await client.instances.search({
|
|
350
|
+
view: {
|
|
351
|
+
externalId: "Equipment",
|
|
352
|
+
space: "cdf_core",
|
|
353
|
+
type: "view",
|
|
354
|
+
version: "v1",
|
|
355
|
+
},
|
|
356
|
+
query: "pump ACME", // Text search
|
|
357
|
+
filter: {
|
|
358
|
+
and: [
|
|
359
|
+
{
|
|
360
|
+
equals: {
|
|
361
|
+
property: ["manufacturer"],
|
|
362
|
+
value: "ACME Corp",
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
range: {
|
|
367
|
+
property: ["installedDate"],
|
|
368
|
+
gte: "2023-01-01",
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
],
|
|
372
|
+
},
|
|
373
|
+
limit: 50,
|
|
374
|
+
});
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### client.instances.aggregate(params)
|
|
378
|
+
|
|
379
|
+
- **Description**: Aggregates instance data with grouping and calculations
|
|
380
|
+
- **Parameters**:
|
|
381
|
+
- `params` (ViewAggregationRequest, required): Aggregation query
|
|
382
|
+
- **Return Type**: Promise<AggregationResponse>
|
|
383
|
+
- **Example**:
|
|
384
|
+
|
|
385
|
+
```javascript
|
|
386
|
+
const aggregation = await client.instances.aggregate({
|
|
387
|
+
view: {
|
|
388
|
+
externalId: "Equipment",
|
|
389
|
+
space: "cdf_core",
|
|
390
|
+
type: "view",
|
|
391
|
+
version: "v1",
|
|
392
|
+
},
|
|
393
|
+
groupBy: ["manufacturer", "equipmentType"],
|
|
394
|
+
aggregates: [
|
|
395
|
+
{ count: { property: "externalId" } },
|
|
396
|
+
{ avg: { property: "maintenanceCost" } },
|
|
397
|
+
{ sum: { property: "powerRating" } },
|
|
398
|
+
],
|
|
399
|
+
filter: {
|
|
400
|
+
prefix: {
|
|
401
|
+
property: ["name"],
|
|
402
|
+
value: "Pump",
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
limit: 10,
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Process results
|
|
409
|
+
for (const group of aggregation.items) {
|
|
410
|
+
console.log(
|
|
411
|
+
`${group.group[0]} - ${group.group[1]}: ${group.aggregates[0].value} units`
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
#### client.instances.query(params)
|
|
417
|
+
|
|
418
|
+
- **Description**: Executes complex queries across multiple node/edge types
|
|
419
|
+
- **Parameters**:
|
|
420
|
+
- `params` (QueryRequest, required): Query definition
|
|
421
|
+
- **Return Type**: Promise<QueryResponse>
|
|
422
|
+
- **Example**:
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
const queryResult = await client.instances.query({
|
|
426
|
+
with: {
|
|
427
|
+
// Define data sources
|
|
428
|
+
pumps: {
|
|
429
|
+
nodes: {
|
|
430
|
+
filter: {
|
|
431
|
+
equals: {
|
|
432
|
+
property: ["node", "type"],
|
|
433
|
+
value: { space: "types", externalId: "Pump" },
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
maintenanceEvents: {
|
|
439
|
+
edges: {
|
|
440
|
+
from: "pumps",
|
|
441
|
+
type: { space: "relationships", externalId: "hasMaintenanceEvent" },
|
|
442
|
+
direction: "outwards",
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
select: {
|
|
447
|
+
// Define what to return
|
|
448
|
+
pumps: {
|
|
449
|
+
sources: [
|
|
450
|
+
{
|
|
451
|
+
source: {
|
|
452
|
+
externalId: "Equipment",
|
|
453
|
+
space: "cdf_core",
|
|
454
|
+
type: "view",
|
|
455
|
+
version: "v1",
|
|
456
|
+
},
|
|
457
|
+
properties: ["name", "serialNumber", "manufacturer"],
|
|
458
|
+
},
|
|
459
|
+
],
|
|
460
|
+
},
|
|
461
|
+
maintenanceEvents: {
|
|
462
|
+
sources: [
|
|
463
|
+
{
|
|
464
|
+
source: {
|
|
465
|
+
externalId: "MaintenanceEvent",
|
|
466
|
+
space: "maintenance",
|
|
467
|
+
type: "view",
|
|
468
|
+
version: "v1",
|
|
469
|
+
},
|
|
470
|
+
properties: ["scheduledDate", "description", "status"],
|
|
471
|
+
},
|
|
472
|
+
],
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
parameters: {
|
|
476
|
+
limit: 100,
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### client.instances.sync(params)
|
|
482
|
+
|
|
483
|
+
- **Description**: Synchronizes data with cursor-based pagination for large datasets
|
|
484
|
+
- **Parameters**:
|
|
485
|
+
- `params` (SyncRequest, required): Sync query with cursor support
|
|
486
|
+
- **Return Type**: Promise<QueryResponse>
|
|
487
|
+
- **Example**:
|
|
488
|
+
|
|
489
|
+
```javascript
|
|
490
|
+
let cursor = null;
|
|
491
|
+
const allData = [];
|
|
492
|
+
|
|
493
|
+
do {
|
|
494
|
+
const syncResult = await client.instances.sync({
|
|
495
|
+
with: {
|
|
496
|
+
equipment: {
|
|
497
|
+
nodes: {
|
|
498
|
+
filter: {
|
|
499
|
+
equals: {
|
|
500
|
+
property: ["node", "space"],
|
|
501
|
+
value: "industrial-assets",
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
},
|
|
507
|
+
select: {
|
|
508
|
+
equipment: {},
|
|
509
|
+
},
|
|
510
|
+
cursors: cursor ? { equipment: cursor } : {},
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
allData.push(...syncResult.items.equipment);
|
|
514
|
+
cursor = syncResult.nextCursor?.equipment;
|
|
515
|
+
} while (cursor);
|
|
516
|
+
|
|
517
|
+
console.log(`Synced ${allData.length} equipment nodes`);
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
#### client.instances.delete(items)
|
|
521
|
+
|
|
522
|
+
- **Description**: Deletes instances by ID
|
|
523
|
+
- **Parameters**:
|
|
524
|
+
- `items` (Array, required): Items to delete
|
|
525
|
+
- **Return Type**: Promise<{}>
|
|
526
|
+
- **Example**:
|
|
527
|
+
|
|
528
|
+
```javascript
|
|
529
|
+
await client.instances.delete([
|
|
530
|
+
{
|
|
531
|
+
instanceType: "node",
|
|
532
|
+
externalId: "pump-001",
|
|
533
|
+
space: "industrial-assets",
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
instanceType: "edge",
|
|
537
|
+
externalId: "located-in-001",
|
|
538
|
+
space: "industrial-assets",
|
|
539
|
+
},
|
|
540
|
+
]);
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Views API
|
|
544
|
+
|
|
545
|
+
Views define the semantic schema for your data, supporting inheritance and property mapping.
|
|
546
|
+
|
|
547
|
+
#### client.views.upsert(params)
|
|
548
|
+
|
|
549
|
+
- **Description**: Creates or updates view definitions
|
|
550
|
+
- **Parameters**:
|
|
551
|
+
- `params` (ViewCreateDefinition[], required): Array of view definitions
|
|
552
|
+
- **Return Type**: Promise<ViewCollectionResponse>
|
|
553
|
+
- **Example**:
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
const views = await client.views.upsert([
|
|
557
|
+
{
|
|
558
|
+
externalId: "Pump",
|
|
559
|
+
space: "equipment-types",
|
|
560
|
+
name: "Pump Equipment",
|
|
561
|
+
description: "View for pump equipment with extended properties",
|
|
562
|
+
version: "v1",
|
|
563
|
+
implements: [
|
|
564
|
+
{
|
|
565
|
+
type: "view",
|
|
566
|
+
space: "cdf_core",
|
|
567
|
+
externalId: "Equipment",
|
|
568
|
+
version: "v1",
|
|
569
|
+
},
|
|
570
|
+
],
|
|
571
|
+
properties: {
|
|
572
|
+
flowRate: {
|
|
573
|
+
container: {
|
|
574
|
+
type: "container",
|
|
575
|
+
space: "equipment-data",
|
|
576
|
+
externalId: "PumpData",
|
|
577
|
+
},
|
|
578
|
+
containerPropertyIdentifier: "flowRate",
|
|
579
|
+
name: "Flow Rate",
|
|
580
|
+
description: "Maximum flow rate in liters per minute",
|
|
581
|
+
},
|
|
582
|
+
pressure: {
|
|
583
|
+
container: {
|
|
584
|
+
type: "container",
|
|
585
|
+
space: "equipment-data",
|
|
586
|
+
externalId: "PumpData",
|
|
587
|
+
},
|
|
588
|
+
containerPropertyIdentifier: "pressure",
|
|
589
|
+
name: "Operating Pressure",
|
|
590
|
+
description: "Operating pressure in bar",
|
|
591
|
+
},
|
|
592
|
+
manufacturer: {
|
|
593
|
+
container: {
|
|
594
|
+
type: "container",
|
|
595
|
+
space: "equipment-data",
|
|
596
|
+
externalId: "EquipmentCore",
|
|
597
|
+
},
|
|
598
|
+
containerPropertyIdentifier: "manufacturer",
|
|
599
|
+
name: "Manufacturer",
|
|
600
|
+
description: "Equipment manufacturer name",
|
|
601
|
+
},
|
|
602
|
+
},
|
|
603
|
+
filter: {
|
|
604
|
+
equals: {
|
|
605
|
+
property: ["node", "type"],
|
|
606
|
+
value: { space: "types", externalId: "Pump" },
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
]);
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
#### client.views.list(params)
|
|
614
|
+
|
|
615
|
+
- **Description**: Lists views with optional filtering
|
|
616
|
+
- **Parameters**:
|
|
617
|
+
- `params` (Object, optional): Query parameters
|
|
618
|
+
- **Return Type**: CursorAndAsyncIterator<ViewDefinition>
|
|
619
|
+
- **Example**:
|
|
620
|
+
|
|
621
|
+
```javascript
|
|
622
|
+
// List all views in a space
|
|
623
|
+
const views = await client.views
|
|
624
|
+
.list({
|
|
625
|
+
space: "equipment-types",
|
|
626
|
+
includeInheritedProperties: true,
|
|
627
|
+
allVersions: false,
|
|
628
|
+
})
|
|
629
|
+
.autoPagingToArray();
|
|
630
|
+
|
|
631
|
+
// List global views
|
|
632
|
+
const globalViews = await client.views
|
|
633
|
+
.list({
|
|
634
|
+
includeGlobal: true,
|
|
635
|
+
limit: 50,
|
|
636
|
+
})
|
|
637
|
+
.autoPagingToArray();
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
#### client.views.retrieve(params, options?)
|
|
641
|
+
|
|
642
|
+
- **Description**: Retrieves specific views by ID
|
|
643
|
+
- **Parameters**:
|
|
644
|
+
- `params` (Array, required): View references
|
|
645
|
+
- `options` (Object, optional): Additional options
|
|
646
|
+
- **Return Type**: Promise<ViewCollectionResponse>
|
|
647
|
+
- **Example**:
|
|
648
|
+
|
|
649
|
+
```javascript
|
|
650
|
+
const views = await client.views.retrieve(
|
|
651
|
+
[
|
|
652
|
+
{
|
|
653
|
+
space: "cdf_core",
|
|
654
|
+
externalId: "Equipment",
|
|
655
|
+
version: "v1",
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
space: "equipment-types",
|
|
659
|
+
externalId: "Pump",
|
|
660
|
+
// Omit version to get latest
|
|
661
|
+
},
|
|
662
|
+
],
|
|
663
|
+
{
|
|
664
|
+
includeInheritedProperties: true,
|
|
665
|
+
}
|
|
666
|
+
);
|
|
667
|
+
|
|
668
|
+
// Inspect view properties
|
|
669
|
+
for (const view of views.items) {
|
|
670
|
+
console.log(`View: ${view.externalId}`);
|
|
671
|
+
console.log(`Properties:`, Object.keys(view.properties || {}));
|
|
672
|
+
console.log(`Implements:`, view.implements);
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
#### client.views.delete(params)
|
|
677
|
+
|
|
678
|
+
- **Description**: Deletes views
|
|
679
|
+
- **Parameters**:
|
|
680
|
+
- `params` (Array, required): View references to delete
|
|
681
|
+
- **Return Type**: Promise<ListOfVersionReferences>
|
|
682
|
+
- **Example**:
|
|
683
|
+
|
|
684
|
+
```javascript
|
|
685
|
+
await client.views.delete([
|
|
686
|
+
{
|
|
687
|
+
space: "equipment-types",
|
|
688
|
+
externalId: "ObsoletePumpView",
|
|
689
|
+
version: "v1",
|
|
690
|
+
},
|
|
691
|
+
]);
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Containers API
|
|
695
|
+
|
|
696
|
+
Containers define the physical storage layer with properties, constraints, and indexes.
|
|
697
|
+
|
|
698
|
+
#### client.containers.upsert(params)
|
|
699
|
+
|
|
700
|
+
- **Description**: Creates or updates container definitions
|
|
701
|
+
- **Parameters**:
|
|
702
|
+
- `params` (ContainerCreateDefinition[], required): Container definitions
|
|
703
|
+
- **Return Type**: Promise<ContainerCollectionResponse>
|
|
704
|
+
- **Example**:
|
|
705
|
+
|
|
706
|
+
```javascript
|
|
707
|
+
const containers = await client.containers.upsert([
|
|
708
|
+
{
|
|
709
|
+
space: "equipment-data",
|
|
710
|
+
externalId: "PumpData",
|
|
711
|
+
name: "Pump Data Container",
|
|
712
|
+
description: "Stores pump-specific properties",
|
|
713
|
+
usedFor: "node", // Can be 'node', 'edge', or 'all'
|
|
714
|
+
properties: {
|
|
715
|
+
flowRate: {
|
|
716
|
+
type: {
|
|
717
|
+
type: "float64",
|
|
718
|
+
},
|
|
719
|
+
nullable: true,
|
|
720
|
+
description: "Flow rate in liters per minute",
|
|
721
|
+
},
|
|
722
|
+
pressure: {
|
|
723
|
+
type: {
|
|
724
|
+
type: "float64",
|
|
725
|
+
},
|
|
726
|
+
nullable: false,
|
|
727
|
+
defaultValue: 1.0,
|
|
728
|
+
description: "Operating pressure in bar",
|
|
729
|
+
},
|
|
730
|
+
manufacturer: {
|
|
731
|
+
type: {
|
|
732
|
+
type: "text",
|
|
733
|
+
list: false,
|
|
734
|
+
},
|
|
735
|
+
nullable: true,
|
|
736
|
+
description: "Manufacturer name",
|
|
737
|
+
},
|
|
738
|
+
installedDate: {
|
|
739
|
+
type: {
|
|
740
|
+
type: "timestamp",
|
|
741
|
+
},
|
|
742
|
+
nullable: true,
|
|
743
|
+
description: "Installation date",
|
|
744
|
+
},
|
|
745
|
+
maintenanceSchedule: {
|
|
746
|
+
type: {
|
|
747
|
+
type: "json",
|
|
748
|
+
},
|
|
749
|
+
nullable: true,
|
|
750
|
+
description: "Maintenance schedule configuration",
|
|
751
|
+
},
|
|
752
|
+
relatedAssets: {
|
|
753
|
+
type: {
|
|
754
|
+
type: "direct",
|
|
755
|
+
container: {
|
|
756
|
+
type: "container",
|
|
757
|
+
space: "cdf_core",
|
|
758
|
+
externalId: "Asset",
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
list: true,
|
|
762
|
+
description: "Related asset references",
|
|
763
|
+
},
|
|
764
|
+
},
|
|
765
|
+
constraints: {
|
|
766
|
+
uniqueSerialNumber: {
|
|
767
|
+
constraintType: "unique",
|
|
768
|
+
properties: ["serialNumber"],
|
|
769
|
+
},
|
|
770
|
+
},
|
|
771
|
+
indexes: {
|
|
772
|
+
byManufacturer: {
|
|
773
|
+
properties: ["manufacturer"],
|
|
774
|
+
},
|
|
775
|
+
byInstallDate: {
|
|
776
|
+
properties: ["installedDate"],
|
|
777
|
+
},
|
|
778
|
+
},
|
|
779
|
+
},
|
|
780
|
+
]);
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
#### client.containers.list(params)
|
|
784
|
+
|
|
785
|
+
- **Description**: Lists containers
|
|
786
|
+
- **Parameters**:
|
|
787
|
+
- `params` (Object, optional): Query parameters
|
|
788
|
+
- **Return Type**: CursorAndAsyncIterator<ContainerDefinition>
|
|
789
|
+
- **Example**:
|
|
790
|
+
|
|
791
|
+
```javascript
|
|
792
|
+
// List containers in a specific space
|
|
793
|
+
const containers = await client.containers
|
|
794
|
+
.list({
|
|
795
|
+
space: "equipment-data",
|
|
796
|
+
includeGlobal: false,
|
|
797
|
+
})
|
|
798
|
+
.autoPagingToArray();
|
|
799
|
+
|
|
800
|
+
// List all accessible containers including global ones
|
|
801
|
+
const allContainers = await client.containers
|
|
802
|
+
.list({
|
|
803
|
+
includeGlobal: true,
|
|
804
|
+
limit: 100,
|
|
805
|
+
})
|
|
806
|
+
.autoPagingToArray();
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
#### client.containers.retrieve(params)
|
|
810
|
+
|
|
811
|
+
- **Description**: Retrieves specific containers
|
|
812
|
+
- **Parameters**:
|
|
813
|
+
- `params` (Array, required): Container identifiers
|
|
814
|
+
- **Return Type**: Promise<ContainerCollectionResponse>
|
|
815
|
+
- **Example**:
|
|
816
|
+
|
|
817
|
+
```javascript
|
|
818
|
+
const containers = await client.containers.retrieve([
|
|
819
|
+
{
|
|
820
|
+
space: "equipment-data",
|
|
821
|
+
externalId: "PumpData",
|
|
822
|
+
},
|
|
823
|
+
{
|
|
824
|
+
space: "cdf_core",
|
|
825
|
+
externalId: "Asset",
|
|
826
|
+
},
|
|
827
|
+
]);
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
#### client.containers.delete(params)
|
|
831
|
+
|
|
832
|
+
- **Description**: Deletes containers
|
|
833
|
+
- **Parameters**:
|
|
834
|
+
- `params` (Array, required): Container identifiers
|
|
835
|
+
- **Return Type**: Promise<ListOfSpaceExternalIdsResponse>
|
|
836
|
+
- **Example**:
|
|
837
|
+
|
|
838
|
+
```javascript
|
|
839
|
+
await client.containers.delete([
|
|
840
|
+
{
|
|
841
|
+
space: "equipment-data",
|
|
842
|
+
externalId: "ObsoleteContainer",
|
|
843
|
+
},
|
|
844
|
+
]);
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
### Data Models API
|
|
848
|
+
|
|
849
|
+
Data models group related views together for specific use cases or applications.
|
|
850
|
+
|
|
851
|
+
#### client.dataModels.upsert(params)
|
|
852
|
+
|
|
853
|
+
- **Description**: Creates or updates data models
|
|
854
|
+
- **Parameters**:
|
|
855
|
+
- `params` (DataModelCreate[], required): Data model definitions
|
|
856
|
+
- **Return Type**: Promise<DataModelCollectionResponse>
|
|
857
|
+
- **Example**:
|
|
858
|
+
|
|
859
|
+
```javascript
|
|
860
|
+
const dataModels = await client.dataModels.upsert([
|
|
861
|
+
{
|
|
862
|
+
space: "industrial-models",
|
|
863
|
+
externalId: "MaintenanceModel",
|
|
864
|
+
name: "Maintenance Management Model",
|
|
865
|
+
description: "Data model for equipment maintenance workflows",
|
|
866
|
+
version: "v1",
|
|
867
|
+
views: [
|
|
868
|
+
// Reference existing views
|
|
869
|
+
{
|
|
870
|
+
type: "view",
|
|
871
|
+
space: "cdf_core",
|
|
872
|
+
externalId: "Asset",
|
|
873
|
+
version: "v1",
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
type: "view",
|
|
877
|
+
space: "equipment-types",
|
|
878
|
+
externalId: "Pump",
|
|
879
|
+
version: "v1",
|
|
880
|
+
},
|
|
881
|
+
// Create new view inline
|
|
882
|
+
{
|
|
883
|
+
externalId: "MaintenanceEvent",
|
|
884
|
+
space: "maintenance",
|
|
885
|
+
version: "v1",
|
|
886
|
+
name: "Maintenance Event",
|
|
887
|
+
description: "Maintenance activities on equipment",
|
|
888
|
+
properties: {
|
|
889
|
+
scheduledDate: {
|
|
890
|
+
container: {
|
|
891
|
+
type: "container",
|
|
892
|
+
space: "maintenance",
|
|
893
|
+
externalId: "MaintenanceData",
|
|
894
|
+
},
|
|
895
|
+
containerPropertyIdentifier: "scheduledDate",
|
|
896
|
+
name: "Scheduled Date",
|
|
897
|
+
},
|
|
898
|
+
completedDate: {
|
|
899
|
+
container: {
|
|
900
|
+
type: "container",
|
|
901
|
+
space: "maintenance",
|
|
902
|
+
externalId: "MaintenanceData",
|
|
903
|
+
},
|
|
904
|
+
containerPropertyIdentifier: "completedDate",
|
|
905
|
+
name: "Completed Date",
|
|
906
|
+
},
|
|
907
|
+
description: {
|
|
908
|
+
container: {
|
|
909
|
+
type: "container",
|
|
910
|
+
space: "maintenance",
|
|
911
|
+
externalId: "MaintenanceData",
|
|
912
|
+
},
|
|
913
|
+
containerPropertyIdentifier: "description",
|
|
914
|
+
name: "Description",
|
|
915
|
+
},
|
|
916
|
+
status: {
|
|
917
|
+
container: {
|
|
918
|
+
type: "container",
|
|
919
|
+
space: "maintenance",
|
|
920
|
+
externalId: "MaintenanceData",
|
|
921
|
+
},
|
|
922
|
+
containerPropertyIdentifier: "status",
|
|
923
|
+
name: "Status",
|
|
924
|
+
},
|
|
925
|
+
},
|
|
926
|
+
},
|
|
927
|
+
],
|
|
928
|
+
},
|
|
929
|
+
]);
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
#### client.dataModels.list(params)
|
|
933
|
+
|
|
934
|
+
- **Description**: Lists data models
|
|
935
|
+
- **Parameters**:
|
|
936
|
+
- `params` (Object, optional): Query parameters
|
|
937
|
+
- **Return Type**: DataModelCollectionResponseWithCursorResponse
|
|
938
|
+
- **Example**:
|
|
939
|
+
|
|
940
|
+
```javascript
|
|
941
|
+
// List all data models
|
|
942
|
+
const models = await client.dataModels.list();
|
|
943
|
+
|
|
944
|
+
// List with inline views expanded
|
|
945
|
+
const modelsWithViews = await client.dataModels.list({
|
|
946
|
+
inlineViews: true,
|
|
947
|
+
includeGlobal: true,
|
|
948
|
+
allVersions: false,
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
// Iterate through models
|
|
952
|
+
await modelsWithViews.autoPagingEach((model) => {
|
|
953
|
+
console.log(`Model: ${model.externalId} v${model.version}`);
|
|
954
|
+
console.log(`Views: ${model.views?.length || 0}`);
|
|
955
|
+
});
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
#### client.dataModels.retrieve(params, options?)
|
|
959
|
+
|
|
960
|
+
- **Description**: Retrieves specific data models
|
|
961
|
+
- **Parameters**:
|
|
962
|
+
- `params` (Array, required): Model references
|
|
963
|
+
- `options` (Object, optional): Additional options
|
|
964
|
+
- **Return Type**: Promise<DataModelCollectionResponse>
|
|
965
|
+
- **Example**:
|
|
966
|
+
|
|
967
|
+
```javascript
|
|
968
|
+
const models = await client.dataModels.retrieve(
|
|
969
|
+
[
|
|
970
|
+
{
|
|
971
|
+
space: "industrial-models",
|
|
972
|
+
externalId: "MaintenanceModel",
|
|
973
|
+
version: "v1",
|
|
974
|
+
},
|
|
975
|
+
],
|
|
976
|
+
{
|
|
977
|
+
inlineViews: true, // Include full view definitions
|
|
978
|
+
}
|
|
979
|
+
);
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
#### client.dataModels.delete(params)
|
|
983
|
+
|
|
984
|
+
- **Description**: Deletes data models
|
|
985
|
+
- **Parameters**:
|
|
986
|
+
- `params` (Array, required): Model references
|
|
987
|
+
- **Return Type**: Promise<ListOfVersionReferences>
|
|
988
|
+
- **Example**:
|
|
989
|
+
|
|
990
|
+
```javascript
|
|
991
|
+
await client.dataModels.delete([
|
|
992
|
+
{
|
|
993
|
+
space: "industrial-models",
|
|
994
|
+
externalId: "DeprecatedModel",
|
|
995
|
+
version: "v1",
|
|
996
|
+
},
|
|
997
|
+
]);
|
|
998
|
+
```
|
|
999
|
+
|
|
1000
|
+
## Data Models
|
|
1001
|
+
|
|
1002
|
+
### Space Structure
|
|
1003
|
+
|
|
1004
|
+
```typescript
|
|
1005
|
+
interface SpaceDefinition {
|
|
1006
|
+
space: string; // Space ID (3-43 chars, alphanumeric with _ and -)
|
|
1007
|
+
name?: string; // Human-readable name
|
|
1008
|
+
description?: string; // Space description
|
|
1009
|
+
createdTime: number; // Creation timestamp (epoch milliseconds)
|
|
1010
|
+
lastUpdatedTime: number; // Last update timestamp
|
|
1011
|
+
isGlobal: boolean; // Whether this is a system/global space
|
|
1012
|
+
}
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
Space IDs must:
|
|
1016
|
+
|
|
1017
|
+
- Start with a letter
|
|
1018
|
+
- Be 3-43 characters long
|
|
1019
|
+
- Contain only letters, numbers, underscores, and hyphens
|
|
1020
|
+
- Not use reserved names: `space`, `cdf`, `dms`, `pg3`, `shared`, `system`, `node`, `edge`
|
|
1021
|
+
|
|
1022
|
+
### Core Property Types
|
|
1023
|
+
|
|
1024
|
+
Properties in containers can have the following types:
|
|
1025
|
+
|
|
1026
|
+
```typescript
|
|
1027
|
+
// Text property
|
|
1028
|
+
{
|
|
1029
|
+
type: "text",
|
|
1030
|
+
list?: boolean, // Array of strings
|
|
1031
|
+
collation?: string, // Collation for sorting
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
// Primitive properties
|
|
1035
|
+
{
|
|
1036
|
+
type: "int32" | "int64" | "float32" | "float64" | "boolean",
|
|
1037
|
+
list?: boolean,
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
// Timestamp property
|
|
1041
|
+
{
|
|
1042
|
+
type: "timestamp",
|
|
1043
|
+
list?: boolean,
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// JSON property
|
|
1047
|
+
{
|
|
1048
|
+
type: "json",
|
|
1049
|
+
list?: boolean,
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// Direct relation (reference to another node)
|
|
1053
|
+
{
|
|
1054
|
+
type: "direct",
|
|
1055
|
+
container?: { // Optional: enforce target node type
|
|
1056
|
+
type: "container",
|
|
1057
|
+
space: string,
|
|
1058
|
+
externalId: string,
|
|
1059
|
+
},
|
|
1060
|
+
list?: boolean,
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
// CDF resource reference
|
|
1064
|
+
{
|
|
1065
|
+
type: "timeseries" | "file" | "sequence",
|
|
1066
|
+
list?: boolean,
|
|
1067
|
+
}
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
### Node Structure
|
|
1071
|
+
|
|
1072
|
+
```typescript
|
|
1073
|
+
interface NodeDefinition {
|
|
1074
|
+
instanceType: "node";
|
|
1075
|
+
space: string;
|
|
1076
|
+
externalId: string;
|
|
1077
|
+
version: number;
|
|
1078
|
+
createdTime: number;
|
|
1079
|
+
lastUpdatedTime: number;
|
|
1080
|
+
deletedTime?: number;
|
|
1081
|
+
|
|
1082
|
+
// Optional type categorization
|
|
1083
|
+
type?: {
|
|
1084
|
+
space: string;
|
|
1085
|
+
externalId: string;
|
|
1086
|
+
};
|
|
1087
|
+
|
|
1088
|
+
// Properties grouped by view/container
|
|
1089
|
+
properties?: {
|
|
1090
|
+
[viewOrContainerKey: string]: {
|
|
1091
|
+
[propertyName: string]: any;
|
|
1092
|
+
};
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
### Edge Structure
|
|
1098
|
+
|
|
1099
|
+
```typescript
|
|
1100
|
+
interface EdgeDefinition {
|
|
1101
|
+
instanceType: "edge";
|
|
1102
|
+
space: string;
|
|
1103
|
+
externalId: string;
|
|
1104
|
+
version: number;
|
|
1105
|
+
createdTime: number;
|
|
1106
|
+
lastUpdatedTime: number;
|
|
1107
|
+
deletedTime?: number;
|
|
1108
|
+
|
|
1109
|
+
// Required edge type
|
|
1110
|
+
type: {
|
|
1111
|
+
space: string;
|
|
1112
|
+
externalId: string;
|
|
1113
|
+
};
|
|
1114
|
+
|
|
1115
|
+
// Required start and end nodes
|
|
1116
|
+
startNode: {
|
|
1117
|
+
space: string;
|
|
1118
|
+
externalId: string;
|
|
1119
|
+
};
|
|
1120
|
+
endNode: {
|
|
1121
|
+
space: string;
|
|
1122
|
+
externalId: string;
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
// Properties grouped by view/container
|
|
1126
|
+
properties?: {
|
|
1127
|
+
[viewOrContainerKey: string]: {
|
|
1128
|
+
[propertyName: string]: any;
|
|
1129
|
+
};
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
```
|
|
1133
|
+
|
|
1134
|
+
### View Structure
|
|
1135
|
+
|
|
1136
|
+
```typescript
|
|
1137
|
+
interface ViewDefinition {
|
|
1138
|
+
space: string;
|
|
1139
|
+
externalId: string;
|
|
1140
|
+
version: string;
|
|
1141
|
+
name?: string;
|
|
1142
|
+
description?: string;
|
|
1143
|
+
createdTime: number;
|
|
1144
|
+
lastUpdatedTime: number;
|
|
1145
|
+
writable: boolean;
|
|
1146
|
+
usedFor: "node" | "edge" | "all";
|
|
1147
|
+
|
|
1148
|
+
// Views this view inherits from
|
|
1149
|
+
implements?: Array<{
|
|
1150
|
+
type: "view";
|
|
1151
|
+
space: string;
|
|
1152
|
+
externalId: string;
|
|
1153
|
+
version: string;
|
|
1154
|
+
}>;
|
|
1155
|
+
|
|
1156
|
+
// Filter to apply to instances
|
|
1157
|
+
filter?: FilterDefinition;
|
|
1158
|
+
|
|
1159
|
+
// Property mappings
|
|
1160
|
+
properties?: {
|
|
1161
|
+
[propertyName: string]: {
|
|
1162
|
+
container: {
|
|
1163
|
+
type: "container";
|
|
1164
|
+
space: string;
|
|
1165
|
+
externalId: string;
|
|
1166
|
+
};
|
|
1167
|
+
containerPropertyIdentifier: string;
|
|
1168
|
+
name?: string;
|
|
1169
|
+
description?: string;
|
|
1170
|
+
// For direct relations
|
|
1171
|
+
source?: ViewReference;
|
|
1172
|
+
};
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
### Container Structure
|
|
1178
|
+
|
|
1179
|
+
```typescript
|
|
1180
|
+
interface ContainerDefinition {
|
|
1181
|
+
space: string;
|
|
1182
|
+
externalId: string;
|
|
1183
|
+
name?: string;
|
|
1184
|
+
description?: string;
|
|
1185
|
+
createdTime?: number;
|
|
1186
|
+
lastUpdatedTime?: number;
|
|
1187
|
+
usedFor?: "node" | "edge" | "all";
|
|
1188
|
+
|
|
1189
|
+
// Property definitions
|
|
1190
|
+
properties: {
|
|
1191
|
+
[propertyName: string]: {
|
|
1192
|
+
type: PropertyType;
|
|
1193
|
+
nullable?: boolean;
|
|
1194
|
+
autoIncrement?: boolean;
|
|
1195
|
+
defaultValue?: any;
|
|
1196
|
+
description?: string;
|
|
1197
|
+
name?: string;
|
|
1198
|
+
};
|
|
1199
|
+
};
|
|
1200
|
+
|
|
1201
|
+
// Constraints
|
|
1202
|
+
constraints?: {
|
|
1203
|
+
[constraintName: string]: {
|
|
1204
|
+
constraintType: "unique" | "required";
|
|
1205
|
+
properties: string[];
|
|
1206
|
+
};
|
|
1207
|
+
};
|
|
1208
|
+
|
|
1209
|
+
// Indexes for performance
|
|
1210
|
+
indexes?: {
|
|
1211
|
+
[indexName: string]: {
|
|
1212
|
+
properties: string[];
|
|
1213
|
+
};
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
### Filter Definitions
|
|
1219
|
+
|
|
1220
|
+
Filters support complex queries using boolean operators and various conditions:
|
|
1221
|
+
|
|
1222
|
+
```typescript
|
|
1223
|
+
// Boolean filters
|
|
1224
|
+
{
|
|
1225
|
+
and: FilterDefinition[];
|
|
1226
|
+
}
|
|
1227
|
+
{
|
|
1228
|
+
or: FilterDefinition[];
|
|
1229
|
+
}
|
|
1230
|
+
{
|
|
1231
|
+
not: FilterDefinition;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// Comparison filters
|
|
1235
|
+
{
|
|
1236
|
+
equals: {
|
|
1237
|
+
property: string[];
|
|
1238
|
+
value: any;
|
|
1239
|
+
};
|
|
1240
|
+
}
|
|
1241
|
+
{
|
|
1242
|
+
in: {
|
|
1243
|
+
property: string[];
|
|
1244
|
+
values: any[];
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
{
|
|
1248
|
+
range: {
|
|
1249
|
+
property: string[];
|
|
1250
|
+
gt?: any;
|
|
1251
|
+
gte?: any;
|
|
1252
|
+
lt?: any;
|
|
1253
|
+
lte?: any;
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
{
|
|
1257
|
+
prefix: {
|
|
1258
|
+
property: string[];
|
|
1259
|
+
value: string;
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
{
|
|
1263
|
+
exists: {
|
|
1264
|
+
property: string[];
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
{
|
|
1268
|
+
containsAny: {
|
|
1269
|
+
property: string[];
|
|
1270
|
+
values: any[];
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
{
|
|
1274
|
+
containsAll: {
|
|
1275
|
+
property: string[];
|
|
1276
|
+
values: any[];
|
|
1277
|
+
};
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
// Nested filter for direct relations
|
|
1281
|
+
{
|
|
1282
|
+
nested: {
|
|
1283
|
+
scope: string[];
|
|
1284
|
+
filter: FilterDefinition;
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// Special filters
|
|
1289
|
+
{
|
|
1290
|
+
hasData: {
|
|
1291
|
+
sources: Array<{
|
|
1292
|
+
type: "view" | "container";
|
|
1293
|
+
space: string;
|
|
1294
|
+
externalId: string;
|
|
1295
|
+
version?: string;
|
|
1296
|
+
}>;
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
{
|
|
1300
|
+
matchAll: {};
|
|
1301
|
+
}
|
|
1302
|
+
```
|
|
1303
|
+
|
|
1304
|
+
## Core Data Model
|
|
1305
|
+
|
|
1306
|
+
CDF provides the Cognite Core Data Model (`cdf_cdm`) as a foundation for industrial data. Key concepts include:
|
|
1307
|
+
|
|
1308
|
+
### Core Features (Reusable Property Sets)
|
|
1309
|
+
|
|
1310
|
+
- **CogniteDescribable**: Provides `name`, `description`, `tags`, and `aliases`
|
|
1311
|
+
- **CogniteSourceable**: Tracks data origin with `sourceId`, `sourceContext`, `source`
|
|
1312
|
+
- **CogniteSchedulable**: Manages time windows with `startTime`, `endTime`, `scheduledStartTime`, `scheduledEndTime`
|
|
1313
|
+
- **CogniteVisualizable**: Links to 3D representations via `object3D`
|
|
1314
|
+
|
|
1315
|
+
### Core Concepts
|
|
1316
|
+
|
|
1317
|
+
- **CogniteAsset**: Represents physical or logical assets in your industrial facility
|
|
1318
|
+
- **CogniteEquipment**: Specialized assets representing industrial equipment
|
|
1319
|
+
- **CogniteTimeSeries**: References to time series data
|
|
1320
|
+
- **CogniteFile**: References to files stored in CDF
|
|
1321
|
+
- **CogniteActivity**: Represents activities or events with time boundaries
|
|
1322
|
+
- **CogniteAnnotation**: Comments or observations on other objects
|
|
1323
|
+
|
|
1324
|
+
### 3D Concepts
|
|
1325
|
+
|
|
1326
|
+
- **Cognite3DModel**: 3D models (CAD, point cloud, 360 images)
|
|
1327
|
+
- **CogniteCADNode**: Individual nodes within CAD models
|
|
1328
|
+
- **CognitePointCloudVolume**: Volumes within point cloud data
|
|
1329
|
+
- **Cognite360Image**: 360-degree photospheres
|
|
1330
|
+
|
|
1331
|
+
## Access Control
|
|
1332
|
+
|
|
1333
|
+
Data modeling uses capability-based access control:
|
|
1334
|
+
|
|
1335
|
+
### Required Capabilities
|
|
1336
|
+
|
|
1337
|
+
```javascript
|
|
1338
|
+
// Basic data model access
|
|
1339
|
+
{
|
|
1340
|
+
dataModelsAcl: ["READ", "WRITE"],
|
|
1341
|
+
dataModelInstancesAcl: ["READ", "WRITE"],
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
// For using core data model
|
|
1345
|
+
{
|
|
1346
|
+
dataModelsAcl: {
|
|
1347
|
+
actions: ["READ"],
|
|
1348
|
+
scope: { spaceIdScope: { spaceIds: ["cdf_cdm"] } }
|
|
1349
|
+
},
|
|
1350
|
+
dataModelInstancesAcl: {
|
|
1351
|
+
actions: ["READ"],
|
|
1352
|
+
scope: { spaceIdScope: { spaceIds: ["cdf_cdm_units"] } }
|
|
1353
|
+
},
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// For specific spaces
|
|
1357
|
+
{
|
|
1358
|
+
dataModelInstancesAcl: {
|
|
1359
|
+
actions: ["READ", "WRITE"],
|
|
1360
|
+
scope: { spaceIdScope: { spaceIds: ["your-space"] } }
|
|
1361
|
+
},
|
|
1362
|
+
}
|
|
1363
|
+
```
|
|
1364
|
+
|
|
1365
|
+
## Error Handling
|
|
1366
|
+
|
|
1367
|
+
The Data Modeling APIs return specific error types:
|
|
1368
|
+
|
|
1369
|
+
### Common Error Scenarios
|
|
1370
|
+
|
|
1371
|
+
```javascript
|
|
1372
|
+
try {
|
|
1373
|
+
await client.instances.upsert({ items: [...] });
|
|
1374
|
+
} catch (error) {
|
|
1375
|
+
if (error instanceof CogniteError) {
|
|
1376
|
+
switch (error.status) {
|
|
1377
|
+
case 400:
|
|
1378
|
+
// Validation errors
|
|
1379
|
+
console.error("Validation failed:", error.errorMessage);
|
|
1380
|
+
if (error.extra?.violations) {
|
|
1381
|
+
// Schema violations
|
|
1382
|
+
console.error("Violations:", error.extra.violations);
|
|
1383
|
+
}
|
|
1384
|
+
break;
|
|
1385
|
+
|
|
1386
|
+
case 409:
|
|
1387
|
+
// Conflict errors (e.g., version mismatch)
|
|
1388
|
+
console.error("Version conflict:", error.errorMessage);
|
|
1389
|
+
break;
|
|
1390
|
+
|
|
1391
|
+
case 422:
|
|
1392
|
+
// Business logic errors
|
|
1393
|
+
console.error("Business rule violation:", error.errorMessage);
|
|
1394
|
+
break;
|
|
1395
|
+
|
|
1396
|
+
default:
|
|
1397
|
+
console.error(`API Error ${error.status}:`, error.errorMessage);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
```
|
|
1402
|
+
|
|
1403
|
+
### Handling Large Result Sets
|
|
1404
|
+
|
|
1405
|
+
```javascript
|
|
1406
|
+
// Use cursor pagination for large datasets
|
|
1407
|
+
async function getAllEquipment() {
|
|
1408
|
+
const allItems = [];
|
|
1409
|
+
let cursor = null;
|
|
1410
|
+
|
|
1411
|
+
do {
|
|
1412
|
+
try {
|
|
1413
|
+
const response = await client.instances.list({
|
|
1414
|
+
instanceType: "node",
|
|
1415
|
+
sources: [
|
|
1416
|
+
{
|
|
1417
|
+
source: {
|
|
1418
|
+
type: "view",
|
|
1419
|
+
space: "cdf_core",
|
|
1420
|
+
externalId: "Equipment",
|
|
1421
|
+
version: "v1",
|
|
1422
|
+
},
|
|
1423
|
+
},
|
|
1424
|
+
],
|
|
1425
|
+
cursor: cursor,
|
|
1426
|
+
limit: 1000,
|
|
1427
|
+
});
|
|
1428
|
+
|
|
1429
|
+
allItems.push(...response.items);
|
|
1430
|
+
cursor = response.nextCursor;
|
|
1431
|
+
} catch (error) {
|
|
1432
|
+
console.error("Failed to fetch page:", error);
|
|
1433
|
+
break;
|
|
1434
|
+
}
|
|
1435
|
+
} while (cursor);
|
|
1436
|
+
|
|
1437
|
+
return allItems;
|
|
1438
|
+
}
|
|
1439
|
+
```
|
|
1440
|
+
|
|
1441
|
+
## Code Example
|
|
1442
|
+
|
|
1443
|
+
Here's a complete example building an industrial data model:
|
|
1444
|
+
|
|
1445
|
+
```javascript
|
|
1446
|
+
import { CogniteClient } from "@cognite/sdk";
|
|
1447
|
+
|
|
1448
|
+
async function buildIndustrialDataModel() {
|
|
1449
|
+
// 1. Initialize client
|
|
1450
|
+
const client = new CogniteClient({
|
|
1451
|
+
appId: "IndustrialDataModeling",
|
|
1452
|
+
project: "my-project",
|
|
1453
|
+
oidcTokenProvider: async () => process.env.CDF_ACCESS_TOKEN,
|
|
1454
|
+
});
|
|
1455
|
+
|
|
1456
|
+
try {
|
|
1457
|
+
// 2. Create spaces for organization
|
|
1458
|
+
console.log("Creating spaces...");
|
|
1459
|
+
await client.spaces.upsert([
|
|
1460
|
+
{
|
|
1461
|
+
space: "equipment",
|
|
1462
|
+
name: "Equipment Management",
|
|
1463
|
+
description: "Space for equipment data models and instances",
|
|
1464
|
+
},
|
|
1465
|
+
{
|
|
1466
|
+
space: "maintenance",
|
|
1467
|
+
name: "Maintenance Operations",
|
|
1468
|
+
description: "Space for maintenance workflows and events",
|
|
1469
|
+
},
|
|
1470
|
+
{
|
|
1471
|
+
space: "types",
|
|
1472
|
+
name: "Type Definitions",
|
|
1473
|
+
description: "Space for type categorization nodes",
|
|
1474
|
+
},
|
|
1475
|
+
{
|
|
1476
|
+
space: "assets",
|
|
1477
|
+
name: "Asset Instances",
|
|
1478
|
+
description: "Space for actual asset instances",
|
|
1479
|
+
},
|
|
1480
|
+
{
|
|
1481
|
+
space: "industrial",
|
|
1482
|
+
name: "Industrial Models",
|
|
1483
|
+
description: "Space for industrial data models",
|
|
1484
|
+
},
|
|
1485
|
+
{
|
|
1486
|
+
space: "relationships",
|
|
1487
|
+
name: "Relationship Types",
|
|
1488
|
+
description: "Space for edge type definitions",
|
|
1489
|
+
},
|
|
1490
|
+
]);
|
|
1491
|
+
|
|
1492
|
+
// 3. Create containers for physical storage
|
|
1493
|
+
console.log("Creating containers...");
|
|
1494
|
+
await client.containers.upsert([
|
|
1495
|
+
{
|
|
1496
|
+
space: "equipment",
|
|
1497
|
+
externalId: "EquipmentData",
|
|
1498
|
+
name: "Equipment Data",
|
|
1499
|
+
description: "Core equipment properties",
|
|
1500
|
+
usedFor: "node",
|
|
1501
|
+
properties: {
|
|
1502
|
+
serialNumber: {
|
|
1503
|
+
type: { type: "text" },
|
|
1504
|
+
nullable: false,
|
|
1505
|
+
description: "Unique serial number",
|
|
1506
|
+
},
|
|
1507
|
+
manufacturer: {
|
|
1508
|
+
type: { type: "text" },
|
|
1509
|
+
nullable: true,
|
|
1510
|
+
},
|
|
1511
|
+
model: {
|
|
1512
|
+
type: { type: "text" },
|
|
1513
|
+
nullable: true,
|
|
1514
|
+
},
|
|
1515
|
+
installationDate: {
|
|
1516
|
+
type: { type: "timestamp" },
|
|
1517
|
+
nullable: true,
|
|
1518
|
+
},
|
|
1519
|
+
specifications: {
|
|
1520
|
+
type: { type: "json" },
|
|
1521
|
+
nullable: true,
|
|
1522
|
+
description: "Technical specifications",
|
|
1523
|
+
},
|
|
1524
|
+
},
|
|
1525
|
+
constraints: {
|
|
1526
|
+
uniqueSerial: {
|
|
1527
|
+
constraintType: "unique",
|
|
1528
|
+
properties: ["serialNumber"],
|
|
1529
|
+
},
|
|
1530
|
+
},
|
|
1531
|
+
},
|
|
1532
|
+
{
|
|
1533
|
+
space: "equipment",
|
|
1534
|
+
externalId: "PumpSpecific",
|
|
1535
|
+
name: "Pump Specific Data",
|
|
1536
|
+
usedFor: "node",
|
|
1537
|
+
properties: {
|
|
1538
|
+
flowRate: {
|
|
1539
|
+
type: { type: "float64" },
|
|
1540
|
+
nullable: true,
|
|
1541
|
+
description: "Flow rate in L/min",
|
|
1542
|
+
},
|
|
1543
|
+
headPressure: {
|
|
1544
|
+
type: { type: "float64" },
|
|
1545
|
+
nullable: true,
|
|
1546
|
+
description: "Head pressure in bar",
|
|
1547
|
+
},
|
|
1548
|
+
efficiency: {
|
|
1549
|
+
type: { type: "float64" },
|
|
1550
|
+
nullable: true,
|
|
1551
|
+
description: "Pump efficiency percentage",
|
|
1552
|
+
},
|
|
1553
|
+
},
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
space: "maintenance",
|
|
1557
|
+
externalId: "MaintenanceData",
|
|
1558
|
+
name: "Maintenance Data",
|
|
1559
|
+
usedFor: "edge",
|
|
1560
|
+
properties: {
|
|
1561
|
+
scheduledDate: {
|
|
1562
|
+
type: { type: "timestamp" },
|
|
1563
|
+
nullable: false,
|
|
1564
|
+
},
|
|
1565
|
+
completedDate: {
|
|
1566
|
+
type: { type: "timestamp" },
|
|
1567
|
+
nullable: true,
|
|
1568
|
+
},
|
|
1569
|
+
cost: {
|
|
1570
|
+
type: { type: "float64" },
|
|
1571
|
+
nullable: true,
|
|
1572
|
+
},
|
|
1573
|
+
notes: {
|
|
1574
|
+
type: { type: "text" },
|
|
1575
|
+
nullable: true,
|
|
1576
|
+
},
|
|
1577
|
+
},
|
|
1578
|
+
},
|
|
1579
|
+
]);
|
|
1580
|
+
|
|
1581
|
+
// 4. Create views for semantic access
|
|
1582
|
+
console.log("Creating views...");
|
|
1583
|
+
await client.views.upsert([
|
|
1584
|
+
{
|
|
1585
|
+
space: "equipment",
|
|
1586
|
+
externalId: "BaseEquipment",
|
|
1587
|
+
version: "v1",
|
|
1588
|
+
name: "Base Equipment",
|
|
1589
|
+
description: "Common equipment properties",
|
|
1590
|
+
properties: {
|
|
1591
|
+
serialNumber: {
|
|
1592
|
+
container: {
|
|
1593
|
+
type: "container",
|
|
1594
|
+
space: "equipment",
|
|
1595
|
+
externalId: "EquipmentData",
|
|
1596
|
+
},
|
|
1597
|
+
containerPropertyIdentifier: "serialNumber",
|
|
1598
|
+
},
|
|
1599
|
+
manufacturer: {
|
|
1600
|
+
container: {
|
|
1601
|
+
type: "container",
|
|
1602
|
+
space: "equipment",
|
|
1603
|
+
externalId: "EquipmentData",
|
|
1604
|
+
},
|
|
1605
|
+
containerPropertyIdentifier: "manufacturer",
|
|
1606
|
+
},
|
|
1607
|
+
model: {
|
|
1608
|
+
container: {
|
|
1609
|
+
type: "container",
|
|
1610
|
+
space: "equipment",
|
|
1611
|
+
externalId: "EquipmentData",
|
|
1612
|
+
},
|
|
1613
|
+
containerPropertyIdentifier: "model",
|
|
1614
|
+
},
|
|
1615
|
+
installationDate: {
|
|
1616
|
+
container: {
|
|
1617
|
+
type: "container",
|
|
1618
|
+
space: "equipment",
|
|
1619
|
+
externalId: "EquipmentData",
|
|
1620
|
+
},
|
|
1621
|
+
containerPropertyIdentifier: "installationDate",
|
|
1622
|
+
},
|
|
1623
|
+
},
|
|
1624
|
+
},
|
|
1625
|
+
{
|
|
1626
|
+
space: "equipment",
|
|
1627
|
+
externalId: "Pump",
|
|
1628
|
+
version: "v1",
|
|
1629
|
+
name: "Pump",
|
|
1630
|
+
description: "Industrial pump with extended properties",
|
|
1631
|
+
implements: [
|
|
1632
|
+
{
|
|
1633
|
+
type: "view",
|
|
1634
|
+
space: "equipment",
|
|
1635
|
+
externalId: "BaseEquipment",
|
|
1636
|
+
version: "v1",
|
|
1637
|
+
},
|
|
1638
|
+
],
|
|
1639
|
+
properties: {
|
|
1640
|
+
flowRate: {
|
|
1641
|
+
container: {
|
|
1642
|
+
type: "container",
|
|
1643
|
+
space: "equipment",
|
|
1644
|
+
externalId: "PumpSpecific",
|
|
1645
|
+
},
|
|
1646
|
+
containerPropertyIdentifier: "flowRate",
|
|
1647
|
+
name: "Flow Rate (L/min)",
|
|
1648
|
+
},
|
|
1649
|
+
headPressure: {
|
|
1650
|
+
container: {
|
|
1651
|
+
type: "container",
|
|
1652
|
+
space: "equipment",
|
|
1653
|
+
externalId: "PumpSpecific",
|
|
1654
|
+
},
|
|
1655
|
+
containerPropertyIdentifier: "headPressure",
|
|
1656
|
+
name: "Head Pressure (bar)",
|
|
1657
|
+
},
|
|
1658
|
+
efficiency: {
|
|
1659
|
+
container: {
|
|
1660
|
+
type: "container",
|
|
1661
|
+
space: "equipment",
|
|
1662
|
+
externalId: "PumpSpecific",
|
|
1663
|
+
},
|
|
1664
|
+
containerPropertyIdentifier: "efficiency",
|
|
1665
|
+
name: "Efficiency (%)",
|
|
1666
|
+
},
|
|
1667
|
+
},
|
|
1668
|
+
filter: {
|
|
1669
|
+
equals: {
|
|
1670
|
+
property: ["node", "type"],
|
|
1671
|
+
value: { space: "types", externalId: "Pump" },
|
|
1672
|
+
},
|
|
1673
|
+
},
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
space: "maintenance",
|
|
1677
|
+
externalId: "MaintenanceEvent",
|
|
1678
|
+
version: "v1",
|
|
1679
|
+
name: "Maintenance Event",
|
|
1680
|
+
description: "Maintenance performed on equipment",
|
|
1681
|
+
properties: {
|
|
1682
|
+
scheduledDate: {
|
|
1683
|
+
container: {
|
|
1684
|
+
type: "container",
|
|
1685
|
+
space: "maintenance",
|
|
1686
|
+
externalId: "MaintenanceData",
|
|
1687
|
+
},
|
|
1688
|
+
containerPropertyIdentifier: "scheduledDate",
|
|
1689
|
+
},
|
|
1690
|
+
completedDate: {
|
|
1691
|
+
container: {
|
|
1692
|
+
type: "container",
|
|
1693
|
+
space: "maintenance",
|
|
1694
|
+
externalId: "MaintenanceData",
|
|
1695
|
+
},
|
|
1696
|
+
containerPropertyIdentifier: "completedDate",
|
|
1697
|
+
},
|
|
1698
|
+
cost: {
|
|
1699
|
+
container: {
|
|
1700
|
+
type: "container",
|
|
1701
|
+
space: "maintenance",
|
|
1702
|
+
externalId: "MaintenanceData",
|
|
1703
|
+
},
|
|
1704
|
+
containerPropertyIdentifier: "cost",
|
|
1705
|
+
name: "Cost (USD)",
|
|
1706
|
+
},
|
|
1707
|
+
notes: {
|
|
1708
|
+
container: {
|
|
1709
|
+
type: "container",
|
|
1710
|
+
space: "maintenance",
|
|
1711
|
+
externalId: "MaintenanceData",
|
|
1712
|
+
},
|
|
1713
|
+
containerPropertyIdentifier: "notes",
|
|
1714
|
+
},
|
|
1715
|
+
},
|
|
1716
|
+
},
|
|
1717
|
+
]);
|
|
1718
|
+
|
|
1719
|
+
// 5. Create data model
|
|
1720
|
+
console.log("Creating data model...");
|
|
1721
|
+
await client.dataModels.upsert([
|
|
1722
|
+
{
|
|
1723
|
+
space: "industrial",
|
|
1724
|
+
externalId: "EquipmentMaintenance",
|
|
1725
|
+
name: "Equipment Maintenance Model",
|
|
1726
|
+
description: "Model for equipment and maintenance management",
|
|
1727
|
+
version: "v1",
|
|
1728
|
+
views: [
|
|
1729
|
+
{
|
|
1730
|
+
type: "view",
|
|
1731
|
+
space: "equipment",
|
|
1732
|
+
externalId: "Pump",
|
|
1733
|
+
version: "v1",
|
|
1734
|
+
},
|
|
1735
|
+
{
|
|
1736
|
+
type: "view",
|
|
1737
|
+
space: "maintenance",
|
|
1738
|
+
externalId: "MaintenanceEvent",
|
|
1739
|
+
version: "v1",
|
|
1740
|
+
},
|
|
1741
|
+
],
|
|
1742
|
+
},
|
|
1743
|
+
]);
|
|
1744
|
+
|
|
1745
|
+
// 6. Create type nodes
|
|
1746
|
+
console.log("Creating type nodes...");
|
|
1747
|
+
await client.instances.upsert({
|
|
1748
|
+
items: [
|
|
1749
|
+
{
|
|
1750
|
+
instanceType: "node",
|
|
1751
|
+
space: "types",
|
|
1752
|
+
externalId: "Pump",
|
|
1753
|
+
},
|
|
1754
|
+
],
|
|
1755
|
+
});
|
|
1756
|
+
|
|
1757
|
+
// 7. Create pump instances
|
|
1758
|
+
console.log("Creating pump instances...");
|
|
1759
|
+
const pumps = await client.instances.upsert({
|
|
1760
|
+
items: [
|
|
1761
|
+
{
|
|
1762
|
+
instanceType: "node",
|
|
1763
|
+
space: "assets",
|
|
1764
|
+
externalId: "pump-001",
|
|
1765
|
+
type: { space: "types", externalId: "Pump" },
|
|
1766
|
+
sources: [
|
|
1767
|
+
{
|
|
1768
|
+
source: {
|
|
1769
|
+
type: "view",
|
|
1770
|
+
space: "equipment",
|
|
1771
|
+
externalId: "Pump",
|
|
1772
|
+
version: "v1",
|
|
1773
|
+
},
|
|
1774
|
+
properties: {
|
|
1775
|
+
serialNumber: "P2024-001",
|
|
1776
|
+
manufacturer: "FlowTech Industries",
|
|
1777
|
+
model: "FT-5000",
|
|
1778
|
+
installationDate: "2024-01-15T10:00:00Z",
|
|
1779
|
+
flowRate: 500.0,
|
|
1780
|
+
headPressure: 10.5,
|
|
1781
|
+
efficiency: 85.0,
|
|
1782
|
+
},
|
|
1783
|
+
},
|
|
1784
|
+
],
|
|
1785
|
+
},
|
|
1786
|
+
{
|
|
1787
|
+
instanceType: "node",
|
|
1788
|
+
space: "assets",
|
|
1789
|
+
externalId: "pump-002",
|
|
1790
|
+
type: { space: "types", externalId: "Pump" },
|
|
1791
|
+
sources: [
|
|
1792
|
+
{
|
|
1793
|
+
source: {
|
|
1794
|
+
type: "view",
|
|
1795
|
+
space: "equipment",
|
|
1796
|
+
externalId: "Pump",
|
|
1797
|
+
version: "v1",
|
|
1798
|
+
},
|
|
1799
|
+
properties: {
|
|
1800
|
+
serialNumber: "P2024-002",
|
|
1801
|
+
manufacturer: "FlowTech Industries",
|
|
1802
|
+
model: "FT-3000",
|
|
1803
|
+
installationDate: "2024-02-01T14:30:00Z",
|
|
1804
|
+
flowRate: 300.0,
|
|
1805
|
+
headPressure: 8.0,
|
|
1806
|
+
efficiency: 82.0,
|
|
1807
|
+
},
|
|
1808
|
+
},
|
|
1809
|
+
],
|
|
1810
|
+
},
|
|
1811
|
+
],
|
|
1812
|
+
});
|
|
1813
|
+
|
|
1814
|
+
// 8. Create maintenance events as edges
|
|
1815
|
+
console.log("Creating maintenance events...");
|
|
1816
|
+
await client.instances.upsert({
|
|
1817
|
+
items: [
|
|
1818
|
+
{
|
|
1819
|
+
instanceType: "edge",
|
|
1820
|
+
space: "maintenance",
|
|
1821
|
+
externalId: "maint-001",
|
|
1822
|
+
type: { space: "relationships", externalId: "hasMaintenanceEvent" },
|
|
1823
|
+
startNode: { space: "assets", externalId: "pump-001" },
|
|
1824
|
+
endNode: { space: "maintenance", externalId: "event-001" },
|
|
1825
|
+
sources: [
|
|
1826
|
+
{
|
|
1827
|
+
source: {
|
|
1828
|
+
type: "view",
|
|
1829
|
+
space: "maintenance",
|
|
1830
|
+
externalId: "MaintenanceEvent",
|
|
1831
|
+
version: "v1",
|
|
1832
|
+
},
|
|
1833
|
+
properties: {
|
|
1834
|
+
scheduledDate: "2024-03-01T08:00:00Z",
|
|
1835
|
+
completedDate: "2024-03-01T12:00:00Z",
|
|
1836
|
+
cost: 1250.0,
|
|
1837
|
+
notes: "Routine maintenance and seal replacement",
|
|
1838
|
+
},
|
|
1839
|
+
},
|
|
1840
|
+
],
|
|
1841
|
+
},
|
|
1842
|
+
],
|
|
1843
|
+
});
|
|
1844
|
+
|
|
1845
|
+
// 9. Query data using the model
|
|
1846
|
+
console.log("Querying pump data with maintenance history...");
|
|
1847
|
+
const queryResult = await client.instances.query({
|
|
1848
|
+
with: {
|
|
1849
|
+
pumps: {
|
|
1850
|
+
nodes: {
|
|
1851
|
+
filter: {
|
|
1852
|
+
and: [
|
|
1853
|
+
{
|
|
1854
|
+
equals: {
|
|
1855
|
+
property: ["node", "type"],
|
|
1856
|
+
value: { space: "types", externalId: "Pump" },
|
|
1857
|
+
},
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
range: {
|
|
1861
|
+
property: ["pump", "efficiency"],
|
|
1862
|
+
gte: 80.0,
|
|
1863
|
+
},
|
|
1864
|
+
},
|
|
1865
|
+
],
|
|
1866
|
+
},
|
|
1867
|
+
},
|
|
1868
|
+
},
|
|
1869
|
+
maintenance: {
|
|
1870
|
+
edges: {
|
|
1871
|
+
from: "pumps",
|
|
1872
|
+
type: { space: "relationships", externalId: "hasMaintenanceEvent" },
|
|
1873
|
+
direction: "outwards",
|
|
1874
|
+
},
|
|
1875
|
+
},
|
|
1876
|
+
},
|
|
1877
|
+
select: {
|
|
1878
|
+
pumps: {
|
|
1879
|
+
sources: [
|
|
1880
|
+
{
|
|
1881
|
+
source: {
|
|
1882
|
+
type: "view",
|
|
1883
|
+
space: "equipment",
|
|
1884
|
+
externalId: "Pump",
|
|
1885
|
+
version: "v1",
|
|
1886
|
+
},
|
|
1887
|
+
properties: [
|
|
1888
|
+
"serialNumber",
|
|
1889
|
+
"manufacturer",
|
|
1890
|
+
"model",
|
|
1891
|
+
"flowRate",
|
|
1892
|
+
"efficiency",
|
|
1893
|
+
],
|
|
1894
|
+
},
|
|
1895
|
+
],
|
|
1896
|
+
},
|
|
1897
|
+
maintenance: {
|
|
1898
|
+
sources: [
|
|
1899
|
+
{
|
|
1900
|
+
source: {
|
|
1901
|
+
type: "view",
|
|
1902
|
+
space: "maintenance",
|
|
1903
|
+
externalId: "MaintenanceEvent",
|
|
1904
|
+
version: "v1",
|
|
1905
|
+
},
|
|
1906
|
+
properties: ["scheduledDate", "completedDate", "cost", "notes"],
|
|
1907
|
+
},
|
|
1908
|
+
],
|
|
1909
|
+
},
|
|
1910
|
+
},
|
|
1911
|
+
});
|
|
1912
|
+
|
|
1913
|
+
console.log("Query results:");
|
|
1914
|
+
console.log(`Found ${queryResult.items.pumps.length} efficient pumps`);
|
|
1915
|
+
queryResult.items.pumps.forEach((pump) => {
|
|
1916
|
+
console.log(`\nPump: ${pump.externalId}`);
|
|
1917
|
+
console.log(
|
|
1918
|
+
`- Serial: ${pump.properties?.equipment?.Pump?.serialNumber}`
|
|
1919
|
+
);
|
|
1920
|
+
console.log(
|
|
1921
|
+
`- Efficiency: ${pump.properties?.equipment?.Pump?.efficiency}%`
|
|
1922
|
+
);
|
|
1923
|
+
});
|
|
1924
|
+
|
|
1925
|
+
// 10. Aggregate maintenance costs
|
|
1926
|
+
console.log("\nAggregating maintenance costs...");
|
|
1927
|
+
const aggregation = await client.instances.aggregate({
|
|
1928
|
+
view: {
|
|
1929
|
+
type: "view",
|
|
1930
|
+
space: "maintenance",
|
|
1931
|
+
externalId: "MaintenanceEvent",
|
|
1932
|
+
version: "v1",
|
|
1933
|
+
},
|
|
1934
|
+
groupBy: ["notes"],
|
|
1935
|
+
aggregates: [
|
|
1936
|
+
{ count: { property: "externalId" } },
|
|
1937
|
+
{ sum: { property: "cost" } },
|
|
1938
|
+
{ avg: { property: "cost" } },
|
|
1939
|
+
],
|
|
1940
|
+
});
|
|
1941
|
+
|
|
1942
|
+
console.log("Maintenance cost summary:");
|
|
1943
|
+
aggregation.items.forEach((group) => {
|
|
1944
|
+
console.log(`- Count: ${group.aggregates[0].value}`);
|
|
1945
|
+
console.log(`- Total cost: $${group.aggregates[1].value}`);
|
|
1946
|
+
console.log(`- Average cost: $${group.aggregates[2].value}`);
|
|
1947
|
+
});
|
|
1948
|
+
} catch (error) {
|
|
1949
|
+
if (error instanceof CogniteError) {
|
|
1950
|
+
console.error(`CDF API Error ${error.status}: ${error.errorMessage}`);
|
|
1951
|
+
if (error.extra) {
|
|
1952
|
+
console.error("Details:", JSON.stringify(error.extra, null, 2));
|
|
1953
|
+
}
|
|
1954
|
+
} else {
|
|
1955
|
+
console.error("Unexpected error:", error);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
// Run the example
|
|
1961
|
+
buildIndustrialDataModel();
|
|
1962
|
+
```
|
|
1963
|
+
|
|
1964
|
+
This example demonstrates:
|
|
1965
|
+
|
|
1966
|
+
- Creating spaces for logical organization
|
|
1967
|
+
- Creating containers to define physical storage
|
|
1968
|
+
- Building views with inheritance and property mapping
|
|
1969
|
+
- Composing data models from views
|
|
1970
|
+
- Creating nodes with typed properties
|
|
1971
|
+
- Establishing relationships using edges
|
|
1972
|
+
- Querying across related data
|
|
1973
|
+
- Aggregating instance data
|
|
1974
|
+
- Handling errors appropriately
|
|
1975
|
+
|
|
1976
|
+
## Best Practices
|
|
1977
|
+
|
|
1978
|
+
1. **Space Organization**
|
|
1979
|
+
|
|
1980
|
+
- Use meaningful space names that reflect organizational structure
|
|
1981
|
+
- Separate concerns (e.g., `equipment`, `maintenance`, `operations`)
|
|
1982
|
+
- Consider access control requirements when designing spaces
|
|
1983
|
+
|
|
1984
|
+
2. **Container Design**
|
|
1985
|
+
|
|
1986
|
+
- Keep containers focused on a single concept
|
|
1987
|
+
- Use appropriate data types and constraints
|
|
1988
|
+
- Add indexes for frequently queried properties
|
|
1989
|
+
- Set sensible defaults and nullable flags
|
|
1990
|
+
|
|
1991
|
+
3. **View Composition**
|
|
1992
|
+
|
|
1993
|
+
- Use inheritance to avoid duplication
|
|
1994
|
+
- Apply filters to create specialized views
|
|
1995
|
+
- Document views thoroughly with descriptions
|
|
1996
|
+
- Version views when making breaking changes
|
|
1997
|
+
|
|
1998
|
+
4. **Data Model Structure**
|
|
1999
|
+
|
|
2000
|
+
- Group related views into cohesive data models
|
|
2001
|
+
- Version data models for application compatibility
|
|
2002
|
+
- Include all necessary views for a use case
|
|
2003
|
+
- Document the intended usage clearly
|
|
2004
|
+
|
|
2005
|
+
5. **Instance Management**
|
|
2006
|
+
|
|
2007
|
+
- Use meaningful external IDs following a naming convention
|
|
2008
|
+
- Leverage node types for categorization
|
|
2009
|
+
- Model relationships explicitly as edges
|
|
2010
|
+
- Include metadata in properties for traceability
|
|
2011
|
+
|
|
2012
|
+
6. **Query Optimization**
|
|
2013
|
+
|
|
2014
|
+
- Use filters to reduce result sets early
|
|
2015
|
+
- Leverage indexes in containers
|
|
2016
|
+
- Paginate large result sets with cursors
|
|
2017
|
+
- Select only needed properties
|
|
2018
|
+
|
|
2019
|
+
7. **Error Handling**
|
|
2020
|
+
- Implement retry logic for transient failures
|
|
2021
|
+
- Handle version conflicts appropriately
|
|
2022
|
+
- Validate data before upserting
|
|
2023
|
+
- Log errors with context for debugging
|