-
Notifications
You must be signed in to change notification settings - Fork 16
/
2-insert-link-to.js
120 lines (104 loc) · 2.83 KB
/
2-insert-link-to.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
'use strict';
class Vertex {
constructor(graph, data) {
this.graph = graph;
this.data = data;
this.links = new Map();
}
link(...args) {
const distinct = new Set(args);
const { links } = this;
const { keyField } = this.graph;
for (const item of distinct) {
const key = item.data[keyField];
links.set(key, item);
}
return this;
}
}
class Cursor {
constructor(vertices) {
this.vertices = vertices;
}
linked(...names) {
const { vertices } = this;
const result = new Set();
for (const vertex of vertices) {
let condition = true;
for (const name of names) {
condition = condition && vertex.links.has(name);
}
if (condition) result.add(vertex);
}
return new Cursor(result);
}
}
class Graph {
constructor(keyField) {
this.keyField = keyField;
this.vertices = new Map();
}
add(data) {
const vertex = new Vertex(this, data);
const key = data[this.keyField];
if (this.vertices.get(key) === undefined) {
this.vertices.set(key, vertex);
}
return vertex;
}
select(query) {
const vertices = new Set();
for (const vertex of this.vertices.values()) {
let condition = true;
const { data } = vertex;
if (data) {
for (const field in query) {
condition = condition && data[field] === query[field];
}
if (condition) vertices.add(vertex);
}
}
return new Cursor(vertices);
}
link(source) {
const { vertices } = this;
const from = vertices.get(source);
return {
to(...destinations) {
if (from) {
destinations.forEach((destination) => {
const target = vertices.get(destination);
if (target) from.link(target);
});
}
}
};
}
insert(records) {
for (const record of records) {
this.add(record);
}
}
}
// Usage
const graph = new Graph('name');
graph.insert([
{ name: 'Marcus Aurelius', city: 'Rome', born: 121, dynasty: 'Antonine' },
{ name: 'Lucius Verus', city: 'Rome', born: 130, dynasty: 'Antonine' },
{ name: 'Antoninus Pius', city: 'Lanuvium', born: 86, dynasty: 'Antonine' },
{ name: 'Hadrian', city: 'Santiponce', born: 76, dynasty: 'Nerva–Trajan' },
{ name: 'Trajan', city: 'Sevilla', born: 98, dynasty: 'Nerva–Trajan' },
]);
graph.link('Marcus Aurelius').to('Lucius Verus');
graph.link('Lucius Verus').to('Trajan', 'Marcus Aurelius', 'Marcus Aurelius');
graph.link('Antoninus Pius').to('Marcus Aurelius', 'Lucius Verus');
graph.link('Hadrian').to('Trajan');
graph.link('Trajan').to('Lucius Verus', 'Marcus Aurelius');
console.dir({ graph }, { depth: null });
const res = graph
.select({ city: 'Rome', dynasty: 'Antonine' })
.linked('Trajan');
console.log('\nQuery result:\n');
for (const item of res.vertices) {
console.dir(item.data);
}