0
# Graph Operations
1
2
Insert, update, and upsert operations for complex nested data structures with relationship handling.
3
4
## Capabilities
5
6
### Insert Graph
7
8
Insert a model graph with nested relations in a single operation.
9
10
```javascript { .api }
11
/**
12
* Insert a graph of models with their relations
13
* @param graph - Object or array of objects representing the model graph
14
* @param options - Insert graph options
15
* @returns QueryBuilder instance
16
*/
17
insertGraph(graph: object | object[], options?: InsertGraphOptions): QueryBuilder;
18
19
/**
20
* Insert graph and return the inserted models
21
* @param graph - Object or array representing the model graph
22
* @param options - Insert graph options
23
* @returns QueryBuilder instance
24
*/
25
insertGraphAndFetch(graph: object | object[], options?: InsertGraphOptions): QueryBuilder;
26
27
interface InsertGraphOptions {
28
relate?: boolean | string[];
29
allowRefs?: boolean;
30
}
31
```
32
33
**Usage Examples:**
34
35
```javascript
36
// Insert person with pets
37
const graph = {
38
firstName: 'John',
39
lastName: 'Doe',
40
pets: [
41
{ name: 'Fluffy', species: 'cat' },
42
{ name: 'Buddy', species: 'dog' }
43
]
44
};
45
46
const inserted = await Person.query()
47
.insertGraphAndFetch(graph);
48
49
// Insert with existing relations (relate option)
50
const graphWithExistingMovie = {
51
firstName: 'Jane',
52
lastName: 'Smith',
53
movies: [
54
{ id: 1 }, // Existing movie to relate
55
{ title: 'New Movie', year: 2023 } // New movie to insert
56
]
57
};
58
59
await Person.query()
60
.insertGraph(graphWithExistingMovie, { relate: true });
61
62
// Insert with references
63
const graphWithRefs = {
64
firstName: 'Alice',
65
lastName: 'Johnson',
66
pets: [
67
{ '#id': 'fluffy', name: 'Fluffy', species: 'cat' },
68
{ name: 'Buddy', species: 'dog', bestFriend: { '#ref': 'fluffy' } }
69
]
70
};
71
72
await Person.query()
73
.insertGraph(graphWithRefs, { allowRefs: true });
74
```
75
76
### Upsert Graph
77
78
Insert or update a model graph, handling both new and existing models.
79
80
```javascript { .api }
81
/**
82
* Upsert (insert or update) a graph of models
83
* @param graph - Object or array representing the model graph
84
* @param options - Upsert graph options
85
* @returns QueryBuilder instance
86
*/
87
upsertGraph(graph: object | object[], options?: UpsertGraphOptions): QueryBuilder;
88
89
/**
90
* Upsert graph and return the resulting models
91
* @param graph - Object or array representing the model graph
92
* @param options - Upsert graph options
93
* @returns QueryBuilder instance
94
*/
95
upsertGraphAndFetch(graph: object | object[], options?: UpsertGraphOptions): QueryBuilder;
96
97
interface UpsertGraphOptions {
98
relate?: boolean | string[];
99
unrelate?: boolean | string[];
100
insertMissing?: boolean | string[];
101
update?: boolean | string[];
102
noInsert?: boolean | string[];
103
noUpdate?: boolean | string[];
104
noDelete?: boolean | string[];
105
noRelate?: boolean | string[];
106
noUnrelate?: boolean | string[];
107
allowRefs?: boolean;
108
}
109
```
110
111
**Usage Examples:**
112
113
```javascript
114
// Basic upsert - update person, insert/update pets
115
const graph = {
116
id: 1, // Existing person
117
firstName: 'John Updated',
118
pets: [
119
{ id: 1, name: 'Fluffy Updated' }, // Update existing pet
120
{ name: 'New Pet', species: 'bird' } // Insert new pet
121
]
122
};
123
124
const result = await Person.query()
125
.upsertGraphAndFetch(graph);
126
127
// Upsert with relation control
128
const graphWithOptions = {
129
id: 1,
130
firstName: 'John',
131
pets: [
132
{ id: 1, name: 'Fluffy' },
133
{ id: 2, name: 'Buddy' }
134
],
135
movies: [
136
{ id: 5 } // Existing movie to relate
137
]
138
};
139
140
await Person.query()
141
.upsertGraph(graphWithOptions, {
142
relate: ['movies'], // Only relate movies, don't update them
143
unrelate: ['movies'], // Unrelate movies not in the graph
144
update: ['pets'], // Allow updating pets
145
insertMissing: ['pets'] // Insert missing pets
146
});
147
148
// Prevent certain operations
149
await Person.query()
150
.upsertGraph(graph, {
151
noDelete: true, // Don't delete related models not in graph
152
noUpdate: ['movies'], // Don't update movies
153
noInsert: ['movies'] // Don't insert new movies
154
});
155
```
156
157
### Graph Expression Object
158
159
Convert relation expressions to object format for programmatic manipulation.
160
161
```javascript { .api }
162
/**
163
* Get the graph expression as an object
164
* @returns Object representation of the graph expression
165
*/
166
graphExpressionObject(): object;
167
```
168
169
### Graph References
170
171
Special properties for creating references within graphs.
172
173
```javascript { .api }
174
// Special graph properties
175
interface GraphParameters {
176
'#dbRef'?: any; // Reference to existing database record
177
'#ref'?: string; // Reference to another object in the graph
178
'#id'?: string; // ID for this object to be referenced by others
179
}
180
```
181
182
**Usage Examples:**
183
184
```javascript
185
// Using #dbRef to reference existing records
186
const graph = {
187
firstName: 'John',
188
pets: [
189
{ '#dbRef': 1 }, // Reference existing pet with ID 1
190
{ name: 'New Pet', species: 'cat' }
191
]
192
};
193
194
// Using #ref and #id for internal references
195
const graph = {
196
firstName: 'Jane',
197
pets: [
198
{
199
'#id': 'pet1',
200
name: 'Fluffy',
201
species: 'cat'
202
},
203
{
204
name: 'Buddy',
205
species: 'dog',
206
playmate: { '#ref': 'pet1' } // Reference to Fluffy
207
}
208
]
209
};
210
```
211
212
### Allow Graph
213
214
Restrict which relations can be inserted/updated in graph operations.
215
216
```javascript { .api }
217
/**
218
* Allow only specific relations in graph operations
219
* @param expression - Relation expression specifying allowed relations
220
* @returns QueryBuilder instance
221
*/
222
allowGraph(expression: string): QueryBuilder;
223
```
224
225
**Usage Examples:**
226
227
```javascript
228
// Only allow inserting pets, not movies
229
await Person.query()
230
.allowGraph('pets')
231
.insertGraph({
232
firstName: 'John',
233
pets: [{ name: 'Fluffy', species: 'cat' }],
234
movies: [{ title: 'Movie' }] // This will be ignored
235
});
236
237
// Allow nested relations
238
await Person.query()
239
.allowGraph('pets.owner.movies')
240
.insertGraph(complexGraph);
241
242
// Allow multiple relations
243
await Person.query()
244
.allowGraph('[pets, movies.actors]')
245
.insertGraph(graph);
246
```
247
248
### Graph Validation
249
250
Control validation during graph operations.
251
252
```javascript { .api }
253
// Options that affect validation
254
interface GraphOperationOptions {
255
skipValidation?: boolean; // Skip JSON schema validation
256
}
257
```
258
259
**Usage Examples:**
260
261
```javascript
262
// Skip validation for performance
263
await Person.query()
264
.insertGraph(largeGraph, {
265
skipValidation: true
266
});
267
```
268
269
### Transaction Integration
270
271
Graph operations work seamlessly with transactions.
272
273
**Usage Examples:**
274
275
```javascript
276
await Person.transaction(async trx => {
277
// All graph operations will be in the same transaction
278
const person = await Person.query(trx)
279
.insertGraphAndFetch(personGraph);
280
281
const updated = await Person.query(trx)
282
.upsertGraphAndFetch(updateGraph);
283
284
// If any operation fails, all will be rolled back
285
});
286
```
287
288
### Error Handling
289
290
Graph operations can throw various errors for constraint violations.
291
292
**Usage Examples:**
293
294
```javascript
295
const { ValidationError, DBError } = require('objection');
296
297
try {
298
await Person.query().insertGraph(invalidGraph);
299
} catch (error) {
300
if (error instanceof ValidationError) {
301
console.log('Validation failed:', error.data);
302
} else if (error instanceof DBError) {
303
console.log('Database constraint violation:', error.message);
304
}
305
}
306
```
307
308
## Types
309
310
```typescript { .api }
311
interface InsertGraphOptions {
312
relate?: boolean | string[];
313
allowRefs?: boolean;
314
}
315
316
interface UpsertGraphOptions {
317
relate?: boolean | string[];
318
unrelate?: boolean | string[];
319
insertMissing?: boolean | string[];
320
update?: boolean | string[];
321
noInsert?: boolean | string[];
322
noUpdate?: boolean | string[];
323
noDelete?: boolean | string[];
324
noRelate?: boolean | string[];
325
noUnrelate?: boolean | string[];
326
allowRefs?: boolean;
327
}
328
329
interface GraphParameters {
330
'#dbRef'?: any;
331
'#ref'?: string;
332
'#id'?: string;
333
}
334
335
type PartialModelGraph<M> = Partial<M> & GraphParameters & {
336
[K in keyof M]?: M[K] extends Model
337
? PartialModelGraph<M[K]>
338
: M[K] extends Array<infer U>
339
? U extends Model
340
? PartialModelGraph<U>[]
341
: M[K]
342
: M[K];
343
};
344
```