-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathedge-manager.js
148 lines (135 loc) · 4.31 KB
/
edge-manager.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
const { DataSource } = require('apollo-datasource');
const { aql } = require('arangojs');
/**
* Manages ArangoDb edges
*
* @class EdgeManager
* @extends {DataSource}
*/
class EdgeManager extends DataSource {
/**
* Creates an instance of EdgeManager.
* @param {Database} db An instance of an ArangoDb Database
* @param {Collection} collection An instance of an ArangoDb Collection
* @memberof EdgeManager
*/
constructor(db, collection) {
super();
this.db = db;
this.collection = collection;
}
/**
* Creates a new edge between two documents
*
* @param {String} from The id of the origin document
* @param {String} to The id of the destination document
* @param {Object} [properties={}] An object with key values describing the relationship
* @returns An object with the new version of the edge
* @memberof EdgeManager
*/
async create(from, to, properties = {}) {
const { new: edge } = await this.collection.save(
{ _from: from, _to: to, ...properties },
{
returnNew: true,
}
);
return { new: edge };
}
/**
* Create a one to many to one relationship. This is useful when bulk operations are possible.
*
* @param {String} fromId The id of the single document
* @param {String[]} toIds An array of ids to the many documents
* @param {Function} [getProperties=() => ({})] A function that resolves the extra properties of each edge
* @param {Object} [opts={}] Options to pass to the create call
* @returns {Object[]} An array of the created edges
* @memberof EdgeManager
*/
async createOneToMany(fromId, toIds, getProperties = () => ({}), opts = {}) {
const edges = toIds.map((toId) => ({
_from: fromId,
_to: toId,
...getProperties(fromId, toId),
}));
return this.createMany(edges, opts);
}
/**
* Create a many to one relationship. This is useful when bulk operations are possible.
*
* @param {String[]} fromIds The ids of the many documents
* @param {String} toId The id of the single document
* @param {Function} [getProperties=() => ({})] A function that resolves the extra properties of each edge
* @param {Object} [opts={}] Options to pass to the create call
* @returns {Object[]} An array of the created edges
* @memberof EdgeManager
*/
async createManyToOne(fromIds, toId, getProperties = () => ({}), opts = {}) {
const edges = fromIds.map((fromId) => ({
_from: fromId,
_to: toId,
...getProperties(fromId, toId),
}));
return this.createMany(edges, opts);
}
/**
* Create many edges in a single database call. This is useful when bulk operations are possible.
*
* @param {Object[]} edges The edges to create
* @returns {Object[]} The created edges
* @memberof EdgeManager
*/
async createMany(edges) {
const query = aql`
FOR edge in ${edges}
UPSERT { _from: edge._from, _to: edge._to }
INSERT edge
UPDATE {}
IN ${aql.literal(this.collection.name)}
RETURN NEW
`;
return this.db.query(query);
}
/**
* Removes an edge from between two documents
*
* @param {String} from The id of the origin document
* @param {String} to The id of the destination document
* @returns An object with the old version of the edge
* @memberof EdgeManager
*/
async remove(from, to) {
const edge = await this.db.query(aql`
FOR edge in ${this.collection}
FILTER edge._from == ${from}
FILTER edge._to == ${to}
REMOVE edge._key IN ${this.collection}
RETURN OLD
`);
if (edge === null) {
throw new Error(`Couldn't find edge`);
}
return { old: edge };
}
/**
* Removes multiple edges by filtering on their _from and _to handles. This is useful when bulk operations are possible.
*
* @param {*} edges
* @returns
* @memberof EdgeManager
*/
async removeMany(edges) {
const query = aql`
FOR edge IN ${edges}
FOR collectionEdge IN ${this.collection}
FILTER collectionEdge._from == edge._from
FILTER collectionEdge._to == edge._to
REMOVE collectionEdge IN ${aql.literal(this.collection.name)}
RETURN OLD
`;
return this.db.query(query);
}
}
module.exports = {
EdgeManager: EdgeManager,
};