grafio-mongo 3.1.0 → 3.3.0
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/dist/MongoStorageProvider.d.ts +17 -2
- package/dist/MongoStorageProvider.js +103 -29
- package/package.json +2 -2
|
@@ -7,6 +7,10 @@ export interface QueryOptionsFilterProperty {
|
|
|
7
7
|
AND?: QueryOptionsFilterProperty[];
|
|
8
8
|
OR?: QueryOptionsFilterProperty[];
|
|
9
9
|
}
|
|
10
|
+
import { GraphError } from 'grafio/errors';
|
|
11
|
+
export declare class IndexAlreadyExistsError extends GraphError {
|
|
12
|
+
constructor(indexName: string);
|
|
13
|
+
}
|
|
10
14
|
export interface MongoStorageProviderOptions {
|
|
11
15
|
graphId?: string;
|
|
12
16
|
nodesCollection?: string;
|
|
@@ -53,8 +57,19 @@ export declare class MongoStorageProvider implements IStorageProvider {
|
|
|
53
57
|
deleteEdge(id: string, transaction?: ITransactionHandle): Promise<void>;
|
|
54
58
|
exportJSON(): Promise<GraphData>;
|
|
55
59
|
importJSON(data: GraphData): Promise<void>;
|
|
56
|
-
createIndex(target: 'node' | 'edge',
|
|
57
|
-
hasIndex(target: 'node' | 'edge',
|
|
60
|
+
createIndex(name: string, target: 'node' | 'edge', propertyKeys: string[]): Promise<void>;
|
|
61
|
+
hasIndex(target: 'node' | 'edge', propertyKeys: string[]): Promise<boolean>;
|
|
62
|
+
getIndex(name: string): Promise<{
|
|
63
|
+
name: string;
|
|
64
|
+
target: 'node' | 'edge';
|
|
65
|
+
propertyKeys: string[];
|
|
66
|
+
} | undefined>;
|
|
67
|
+
deleteIndex(name: string): Promise<void>;
|
|
68
|
+
getIndexes(): Promise<{
|
|
69
|
+
name: string;
|
|
70
|
+
target: 'node' | 'edge';
|
|
71
|
+
propertyKeys: string[];
|
|
72
|
+
}[]>;
|
|
58
73
|
addProperty(target: 'node' | 'edge', id: string, key: string, value: unknown, transaction?: ITransactionHandle): Promise<void>;
|
|
59
74
|
updateProperty(target: 'node' | 'edge', id: string, key: string, value: unknown, transaction?: ITransactionHandle): Promise<void>;
|
|
60
75
|
deleteProperty(target: 'node' | 'edge', id: string, key: string, transaction?: ITransactionHandle): Promise<void>;
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MongoStorageProvider = void 0;
|
|
3
|
+
exports.MongoStorageProvider = exports.IndexAlreadyExistsError = void 0;
|
|
4
4
|
const mongodb_1 = require("mongodb");
|
|
5
5
|
const grafio_1 = require("grafio");
|
|
6
6
|
const errors_1 = require("grafio/errors");
|
|
7
|
+
class IndexAlreadyExistsError extends errors_1.GraphError {
|
|
8
|
+
constructor(indexName) {
|
|
9
|
+
super(`Index '${indexName}' already exists`);
|
|
10
|
+
this.name = 'IndexAlreadyExistsError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.IndexAlreadyExistsError = IndexAlreadyExistsError;
|
|
7
14
|
class MongoStorageProvider {
|
|
8
15
|
_nodes;
|
|
9
16
|
_edges;
|
|
@@ -35,6 +42,8 @@ class MongoStorageProvider {
|
|
|
35
42
|
await this._edges.createIndex({ graphId: 1, targetId: 1, type: 1 }, { name: 'edge_graph_target_type' });
|
|
36
43
|
}
|
|
37
44
|
async clear() {
|
|
45
|
+
const indexes = await this.getIndexes();
|
|
46
|
+
await Promise.all(indexes.map(index => this.deleteIndex(index.name)));
|
|
38
47
|
await Promise.all([
|
|
39
48
|
this._nodes.deleteMany({ graphId: this._graphId }),
|
|
40
49
|
this._edges.deleteMany({ graphId: this._graphId }),
|
|
@@ -373,42 +382,107 @@ class MongoStorageProvider {
|
|
|
373
382
|
}
|
|
374
383
|
}
|
|
375
384
|
}
|
|
376
|
-
async createIndex(target,
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
});
|
|
383
|
-
await this._nodes.createIndex({ ...indexFields, type: 1 }, {
|
|
384
|
-
name: `node_graphId_type_${propertyKey}`,
|
|
385
|
-
background: true
|
|
386
|
-
});
|
|
385
|
+
async createIndex(name, target, propertyKeys) {
|
|
386
|
+
const sortedPropertyKeys = [...propertyKeys].sort();
|
|
387
|
+
const metadataCollection = this._nodes.db.collection('grafio_index_metadata');
|
|
388
|
+
const existing = await metadataCollection.findOne({ name, graphId: this._graphId });
|
|
389
|
+
if (existing) {
|
|
390
|
+
throw new IndexAlreadyExistsError(name);
|
|
387
391
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
392
|
+
await metadataCollection.insertOne({
|
|
393
|
+
name,
|
|
394
|
+
graphId: this._graphId,
|
|
395
|
+
target,
|
|
396
|
+
propertyKeys: sortedPropertyKeys,
|
|
397
|
+
createdOn: Date.now()
|
|
398
|
+
});
|
|
399
|
+
for (const propertyKey of sortedPropertyKeys) {
|
|
400
|
+
if (target === 'node') {
|
|
401
|
+
const indexFields = { graphId: 1, [`properties.${propertyKey}`]: 1 };
|
|
402
|
+
await this._nodes.createIndex(indexFields, {
|
|
403
|
+
name: `${name}_node_graphId_${propertyKey}`,
|
|
404
|
+
background: true
|
|
405
|
+
});
|
|
406
|
+
await this._nodes.createIndex({ ...indexFields, type: 1 }, {
|
|
407
|
+
name: `${name}_node_graphId_type_${propertyKey}`,
|
|
408
|
+
background: true
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
const indexFields = { graphId: 1, [`properties.${propertyKey}`]: 1 };
|
|
413
|
+
await this._edges.createIndex(indexFields, {
|
|
414
|
+
name: `${name}_edge_graphId_${propertyKey}`,
|
|
415
|
+
background: true
|
|
416
|
+
});
|
|
417
|
+
await this._edges.createIndex({ ...indexFields, type: 1 }, {
|
|
418
|
+
name: `${name}_edge_graphId_type_${propertyKey}`,
|
|
419
|
+
background: true
|
|
420
|
+
});
|
|
421
|
+
}
|
|
398
422
|
}
|
|
399
423
|
}
|
|
400
|
-
async hasIndex(target,
|
|
401
|
-
const
|
|
402
|
-
const
|
|
403
|
-
const
|
|
404
|
-
for await (const
|
|
405
|
-
const
|
|
406
|
-
|
|
424
|
+
async hasIndex(target, propertyKeys) {
|
|
425
|
+
const sortedPropertyKeys = [...propertyKeys].sort();
|
|
426
|
+
const metadataCollection = this._nodes.db.collection('grafio_index_metadata');
|
|
427
|
+
const cursor = metadataCollection.find({ graphId: this._graphId, target });
|
|
428
|
+
for await (const metadata of cursor) {
|
|
429
|
+
const indexPropertyKeys = metadata.propertyKeys;
|
|
430
|
+
const sortedIndexPropertyKeys = [...indexPropertyKeys].sort();
|
|
431
|
+
const hasAllKeys = sortedPropertyKeys.every(key => sortedIndexPropertyKeys.includes(key));
|
|
432
|
+
if (hasAllKeys) {
|
|
407
433
|
return true;
|
|
408
434
|
}
|
|
409
435
|
}
|
|
410
436
|
return false;
|
|
411
437
|
}
|
|
438
|
+
async getIndex(name) {
|
|
439
|
+
const metadataCollection = this._nodes.db.collection('grafio_index_metadata');
|
|
440
|
+
const metadata = await metadataCollection.findOne({ name, graphId: this._graphId });
|
|
441
|
+
if (!metadata) {
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
name: metadata.name,
|
|
446
|
+
target: metadata.target,
|
|
447
|
+
propertyKeys: metadata.propertyKeys
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
async deleteIndex(name) {
|
|
451
|
+
const metadataCollection = this._nodes.db.collection('grafio_index_metadata');
|
|
452
|
+
const metadata = await metadataCollection.findOne({ name, graphId: this._graphId });
|
|
453
|
+
if (!metadata) {
|
|
454
|
+
throw new Error(`Index with name '${name}' does not exist`);
|
|
455
|
+
}
|
|
456
|
+
const target = metadata.target;
|
|
457
|
+
const propertyKeys = metadata.propertyKeys;
|
|
458
|
+
const collection = target === 'node' ? this._nodes : this._edges;
|
|
459
|
+
for (const propertyKey of propertyKeys) {
|
|
460
|
+
try {
|
|
461
|
+
await collection.dropIndex(`${name}_${target === 'node' ? 'node' : 'edge'}_graphId_${propertyKey}`);
|
|
462
|
+
}
|
|
463
|
+
catch {
|
|
464
|
+
}
|
|
465
|
+
try {
|
|
466
|
+
await collection.dropIndex(`${name}_${target === 'node' ? 'node' : 'edge'}_graphId_type_${propertyKey}`);
|
|
467
|
+
}
|
|
468
|
+
catch {
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
await metadataCollection.deleteOne({ name, graphId: this._graphId });
|
|
472
|
+
}
|
|
473
|
+
async getIndexes() {
|
|
474
|
+
const metadataCollection = this._nodes.db.collection('grafio_index_metadata');
|
|
475
|
+
const cursor = metadataCollection.find({ graphId: this._graphId });
|
|
476
|
+
const indexes = [];
|
|
477
|
+
for await (const metadata of cursor) {
|
|
478
|
+
indexes.push({
|
|
479
|
+
name: metadata.name,
|
|
480
|
+
target: metadata.target,
|
|
481
|
+
propertyKeys: metadata.propertyKeys
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
return indexes;
|
|
485
|
+
}
|
|
412
486
|
async addProperty(target, id, key, value, transaction) {
|
|
413
487
|
if (!(0, grafio_1.isPrimitive)(value)) {
|
|
414
488
|
throw new errors_1.InvalidPropertyError(key, value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grafio-mongo",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "MongoDB storage backend for grafio",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"grafio": ">=7.
|
|
19
|
+
"grafio": ">=7.2.0",
|
|
20
20
|
"mongodb": ">=5.0.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|