@peerbit/indexer-simple 0.0.1-cccc078
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/src/index.d.ts +44 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +452 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +66 -0
- package/src/index.ts +566 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as types from "@peerbit/indexer-interface";
|
|
2
|
+
export declare class HashmapIndex<T extends Record<string, any>, NestedType = any> implements types.Index<T, NestedType> {
|
|
3
|
+
private _index;
|
|
4
|
+
private _resultsCollectQueue;
|
|
5
|
+
private indexByArr;
|
|
6
|
+
private properties;
|
|
7
|
+
init(properties: types.IndexEngineInitProperties<T, NestedType>): this;
|
|
8
|
+
get(id: types.IdKey): Promise<types.IndexedResult<T> | undefined>;
|
|
9
|
+
put(value: T, id?: types.IdKey): void;
|
|
10
|
+
del(query: types.DeleteRequest): Promise<types.IdKey[]>;
|
|
11
|
+
getSize(): number | Promise<number>;
|
|
12
|
+
iterator(): IterableIterator<[string | number | bigint, types.IndexedValue<T>]>;
|
|
13
|
+
start(): void | Promise<void>;
|
|
14
|
+
stop(): void | Promise<void>;
|
|
15
|
+
drop(): void;
|
|
16
|
+
sum(query: types.SumRequest): Promise<number | bigint>;
|
|
17
|
+
count(query: types.CountRequest): Promise<number>;
|
|
18
|
+
private queryAll;
|
|
19
|
+
query(query: types.SearchRequest, properties: {
|
|
20
|
+
reference?: boolean;
|
|
21
|
+
}): Promise<types.IndexedResults<T>>;
|
|
22
|
+
next(query: types.CollectNextRequest): Promise<types.IndexedResults<T>>;
|
|
23
|
+
close(query: types.CloseIteratorRequest): void;
|
|
24
|
+
private handleFieldQuery;
|
|
25
|
+
private handleQueryObject;
|
|
26
|
+
private handleStringMatch;
|
|
27
|
+
private _queryDocuments;
|
|
28
|
+
getPending(cursorId: string): number | undefined;
|
|
29
|
+
get cursorCount(): number;
|
|
30
|
+
}
|
|
31
|
+
export declare class HashmapIndices implements types.Indices {
|
|
32
|
+
private scopes;
|
|
33
|
+
private indices;
|
|
34
|
+
private closed;
|
|
35
|
+
constructor();
|
|
36
|
+
init<T extends Record<string, any>, NestedType>(properties: types.IndexEngineInitProperties<T, any>): Promise<HashmapIndex<T, NestedType>>;
|
|
37
|
+
scope(name: string): Promise<types.Indices>;
|
|
38
|
+
start(): Promise<void>;
|
|
39
|
+
stop(): Promise<void>;
|
|
40
|
+
drop(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
declare const create: () => HashmapIndices;
|
|
43
|
+
export { create };
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,4BAA4B,CAAC;AAqEpD,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,GAAG,CACxE,YAAW,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;IAErC,OAAO,CAAC,MAAM,CAAuD;IACrE,OAAO,CAAC,oBAAoB,CAGzB;IAEH,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,UAAU,CAAiD;IAEnE,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,UAAU,CAAC;IAuBzD,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAWvE,GAAG,CACF,KAAK,EAAE,CAAC,EACR,EAAE,cAA8D,GAC9D,IAAI;IAID,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAU7D,OAAO,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAInC,QAAQ;IAKR,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7B,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5B,IAAI;IAgBE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAiBtD,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;YAIzC,QAAQ;IAwChB,KAAK,CACV,KAAK,EAAE,KAAK,CAAC,aAAa,EAC1B,UAAU,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GACjC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAqC7B,IAAI,CACT,KAAK,EAAE,KAAK,CAAC,kBAAkB,GAC7B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IA4BnC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,GAAG,IAAI;YAIhC,gBAAgB;YA0FhB,iBAAiB;IAwD/B,OAAO,CAAC,iBAAiB;YAmBX,eAAe;IAa7B,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD,IAAI,WAAW,IAAI,MAAM,CAExB;CACD;AAED,qBAAa,cAAe,YAAW,KAAK,CAAC,OAAO;IACnD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,OAAO,CAAwD;IACvE,OAAO,CAAC,MAAM,CAAU;;IAMlB,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EACnD,UAAU,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,GAAG,CAAC;IAmB9C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;IAY3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3B;AAED,QAAA,MAAM,MAAM,sBAA6B,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { deserialize, serialize } from "@dao-xyz/borsh";
|
|
2
|
+
import { Cache } from "@peerbit/cache";
|
|
3
|
+
import * as types from "@peerbit/indexer-interface";
|
|
4
|
+
import { logger as loggerFn } from "@peerbit/logger";
|
|
5
|
+
import { equals } from "uint8arrays";
|
|
6
|
+
const logger = loggerFn({ module: "simple-index-engine" });
|
|
7
|
+
const getBatchFromResults = (results, wantedSize) => {
|
|
8
|
+
const batch = [];
|
|
9
|
+
/* let size = 0; */
|
|
10
|
+
for (const result of results) {
|
|
11
|
+
batch.push(result);
|
|
12
|
+
/* size += types.extractFieldValue<number>(result, properties.sizeProperty);
|
|
13
|
+
if (size > properties.maxSize) {
|
|
14
|
+
break;
|
|
15
|
+
} */
|
|
16
|
+
if (wantedSize <= batch.length) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
results.splice(0, batch.length);
|
|
21
|
+
return batch;
|
|
22
|
+
};
|
|
23
|
+
/* const resolveNestedAliasesRecursively = (request: types.SearchRequest) => {
|
|
24
|
+
const map = new Map();
|
|
25
|
+
for (const query of request.query) {
|
|
26
|
+
_resolveNestedAliasesRecursively(query, map);
|
|
27
|
+
}
|
|
28
|
+
return map;
|
|
29
|
+
}
|
|
30
|
+
*/
|
|
31
|
+
const cloneResults = (indexed, schema) => {
|
|
32
|
+
return indexed.map((x) => {
|
|
33
|
+
return { id: x.id, value: deserialize(serialize(x.value), schema) };
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
/*
|
|
37
|
+
const _resolveNestedAliasesRecursively = (query: types.Query, aliases: Map<string, string>) => {
|
|
38
|
+
|
|
39
|
+
if (query instanceof types.Nested) {
|
|
40
|
+
aliases.set(query.id, query.path);
|
|
41
|
+
for (const subQuery of query.query) {
|
|
42
|
+
_resolveNestedAliasesRecursively(subQuery, aliases);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else if (query instanceof types.And) {
|
|
46
|
+
for (const subQuery of query.and) {
|
|
47
|
+
_resolveNestedAliasesRecursively(subQuery, aliases);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (query instanceof types.Or) {
|
|
51
|
+
for (const subQuery of query.or) {
|
|
52
|
+
_resolveNestedAliasesRecursively(subQuery, aliases);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (query instanceof types.Not) {
|
|
56
|
+
_resolveNestedAliasesRecursively(query.not, aliases);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
*/
|
|
61
|
+
export class HashmapIndex {
|
|
62
|
+
_index;
|
|
63
|
+
_resultsCollectQueue;
|
|
64
|
+
indexByArr;
|
|
65
|
+
properties;
|
|
66
|
+
init(properties) {
|
|
67
|
+
this.properties = properties;
|
|
68
|
+
this._index = new Map();
|
|
69
|
+
this._resultsCollectQueue = new Cache({ max: 10000 }); // TODO choose limit better
|
|
70
|
+
if (properties.indexBy) {
|
|
71
|
+
this.indexByArr = Array.isArray(properties.indexBy)
|
|
72
|
+
? properties.indexBy
|
|
73
|
+
: [properties.indexBy];
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const indexBy = types.getIdProperty(properties.schema);
|
|
77
|
+
if (!indexBy) {
|
|
78
|
+
throw new Error("No indexBy property defined nor schema has a property decorated with `id({ type: '...' })`");
|
|
79
|
+
}
|
|
80
|
+
this.indexByArr = indexBy;
|
|
81
|
+
}
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
async get(id) {
|
|
85
|
+
const value = this._index.get(id.primitive);
|
|
86
|
+
if (!value) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
id,
|
|
91
|
+
value: value.value,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
put(value, id = types.toId(types.extractFieldValue(value, this.indexByArr))) {
|
|
95
|
+
this._index.set(id.primitive, { id, value });
|
|
96
|
+
}
|
|
97
|
+
async del(query) {
|
|
98
|
+
let deleted = [];
|
|
99
|
+
for (const doc of await this.queryAll(query)) {
|
|
100
|
+
if (this._index.delete(doc.id.primitive)) {
|
|
101
|
+
deleted.push(doc.id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return deleted;
|
|
105
|
+
}
|
|
106
|
+
getSize() {
|
|
107
|
+
return this._index.size;
|
|
108
|
+
}
|
|
109
|
+
iterator() {
|
|
110
|
+
// return a iterator if key value pairs, where the value is the indexed record
|
|
111
|
+
return this._index.entries();
|
|
112
|
+
}
|
|
113
|
+
start() {
|
|
114
|
+
// nothing to do
|
|
115
|
+
}
|
|
116
|
+
stop() {
|
|
117
|
+
this._resultsCollectQueue.clear();
|
|
118
|
+
}
|
|
119
|
+
drop() {
|
|
120
|
+
this._index.clear();
|
|
121
|
+
this._resultsCollectQueue.clear();
|
|
122
|
+
/* for (const subindex of this.subIndices) {
|
|
123
|
+
subindex[1].clear()
|
|
124
|
+
} */
|
|
125
|
+
}
|
|
126
|
+
/* subindex(name: string): types.IndexEngine<any> {
|
|
127
|
+
|
|
128
|
+
const subIndex = new HashmapIndexEngine();
|
|
129
|
+
this.subIndices.set(name, subIndex);
|
|
130
|
+
return subIndex;
|
|
131
|
+
}
|
|
132
|
+
*/
|
|
133
|
+
async sum(query) {
|
|
134
|
+
let sum = undefined;
|
|
135
|
+
for (const doc of await this.queryAll(query)) {
|
|
136
|
+
let value = doc.value;
|
|
137
|
+
for (const path of query.key) {
|
|
138
|
+
value = value[path];
|
|
139
|
+
}
|
|
140
|
+
if (typeof value === "number") {
|
|
141
|
+
sum = (sum || 0) + value;
|
|
142
|
+
}
|
|
143
|
+
else if (typeof value === "bigint") {
|
|
144
|
+
sum = (sum || 0n) + value;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return sum != null ? sum : 0;
|
|
148
|
+
}
|
|
149
|
+
async count(query) {
|
|
150
|
+
return (await this.queryAll(query)).length;
|
|
151
|
+
}
|
|
152
|
+
async queryAll(query) {
|
|
153
|
+
if (query.query.length === 1 &&
|
|
154
|
+
(query.query[0] instanceof types.ByteMatchQuery ||
|
|
155
|
+
query.query[0] instanceof types.StringMatch) &&
|
|
156
|
+
types.stringArraysEquals(query.query[0].key, this.indexByArr)) {
|
|
157
|
+
const firstQuery = query.query[0];
|
|
158
|
+
if (firstQuery instanceof types.ByteMatchQuery) {
|
|
159
|
+
const doc = this._index.get(types.toId(firstQuery.value).primitive);
|
|
160
|
+
return doc ? [doc] : [];
|
|
161
|
+
}
|
|
162
|
+
else if (firstQuery instanceof types.StringMatch &&
|
|
163
|
+
firstQuery.method === types.StringMatchMethod.exact &&
|
|
164
|
+
firstQuery.caseInsensitive === false) {
|
|
165
|
+
const doc = this._index.get(firstQuery.value);
|
|
166
|
+
return doc ? [doc] : [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Handle query normally
|
|
170
|
+
const indexedDocuments = await this._queryDocuments(async (doc) => {
|
|
171
|
+
for (const f of query.query) {
|
|
172
|
+
if (!(await this.handleQueryObject(f, doc.value))) {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return true;
|
|
177
|
+
});
|
|
178
|
+
return indexedDocuments;
|
|
179
|
+
}
|
|
180
|
+
async query(query, properties) {
|
|
181
|
+
const indexedDocuments = await this.queryAll(query);
|
|
182
|
+
if (indexedDocuments.length <= 1) {
|
|
183
|
+
return {
|
|
184
|
+
kept: 0,
|
|
185
|
+
results: indexedDocuments,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/* const aliases = resolveNestedAliasesRecursively(query) */
|
|
189
|
+
// Sort
|
|
190
|
+
indexedDocuments.sort((a, b) => types.extractSortCompare(a.value, b.value, query.sort));
|
|
191
|
+
const batch = getBatchFromResults(indexedDocuments, query.fetch);
|
|
192
|
+
if (indexedDocuments.length > 0) {
|
|
193
|
+
this._resultsCollectQueue.add(query.idString, {
|
|
194
|
+
arr: indexedDocuments,
|
|
195
|
+
reference: properties?.reference,
|
|
196
|
+
}); // cache resulst not returned
|
|
197
|
+
}
|
|
198
|
+
// TODO dont leak kept if canRead is defined, or return something random
|
|
199
|
+
return {
|
|
200
|
+
kept: indexedDocuments.length,
|
|
201
|
+
results: properties?.reference
|
|
202
|
+
? batch
|
|
203
|
+
: cloneResults(batch, this.properties.schema),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
async next(query) {
|
|
207
|
+
const results = this._resultsCollectQueue.get(query.idString);
|
|
208
|
+
if (!results) {
|
|
209
|
+
return {
|
|
210
|
+
results: [],
|
|
211
|
+
kept: 0,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
const batch = getBatchFromResults(results.arr, query.amount);
|
|
215
|
+
if (results.arr.length === 0) {
|
|
216
|
+
this._resultsCollectQueue.del(query.idString); // TODO add tests for proper cleanup/timeouts
|
|
217
|
+
}
|
|
218
|
+
// TODO dont leak kept if canRead is defined, or return something random
|
|
219
|
+
return {
|
|
220
|
+
results: results.reference
|
|
221
|
+
? batch
|
|
222
|
+
: cloneResults(batch, this.properties.schema),
|
|
223
|
+
kept: results.arr.length,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
close(query) {
|
|
227
|
+
this._resultsCollectQueue.del(query.idString);
|
|
228
|
+
}
|
|
229
|
+
async handleFieldQuery(f, obj, startIndex) {
|
|
230
|
+
// this clause is needed if we have a field that is of type [][] (we will recursively go through each subarray)
|
|
231
|
+
if (Array.isArray(obj) ||
|
|
232
|
+
(obj instanceof Uint8Array && f instanceof types.ByteMatchQuery === false)) {
|
|
233
|
+
for (const element of obj) {
|
|
234
|
+
if (await this.handleFieldQuery(f, element, startIndex)) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
// Resolve the field from the key path. If we reach an array or nested Document store,
|
|
241
|
+
// then do a recursive call or a search to look into them
|
|
242
|
+
for (let i = startIndex; i < f.key.length; i++) {
|
|
243
|
+
obj = obj[f.key[i]];
|
|
244
|
+
if (Array.isArray(obj) ||
|
|
245
|
+
(obj instanceof Uint8Array &&
|
|
246
|
+
f instanceof types.ByteMatchQuery === false)) {
|
|
247
|
+
for (const element of obj) {
|
|
248
|
+
if (await this.handleFieldQuery(f, element, i + 1)) {
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
if (this.properties.nested?.match(obj)) {
|
|
255
|
+
const queryCloned = f.clone();
|
|
256
|
+
queryCloned.key.splice(0, i + 1); // remove key path until the document store
|
|
257
|
+
const results = await this.properties.nested.query(obj, new types.SearchRequest({ query: [queryCloned] }));
|
|
258
|
+
return results.length > 0 ? true : false; // TODO return INNER HITS?
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (f instanceof types.IsNull) {
|
|
262
|
+
if (obj == null) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
if (obj == null) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
// When we reach here, the field value (obj) is comparable
|
|
271
|
+
if (f instanceof types.StringMatch) {
|
|
272
|
+
let compare = f.value;
|
|
273
|
+
if (f.caseInsensitive) {
|
|
274
|
+
compare = compare.toLowerCase();
|
|
275
|
+
}
|
|
276
|
+
if (this.handleStringMatch(f, compare, obj)) {
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
else if (f instanceof types.ByteMatchQuery) {
|
|
282
|
+
if (obj instanceof Uint8Array === false) {
|
|
283
|
+
if (types.stringArraysEquals(f.key, this.indexByArr)) {
|
|
284
|
+
return f.valueString === obj;
|
|
285
|
+
}
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
return equals(obj, f.value);
|
|
289
|
+
}
|
|
290
|
+
else if (f instanceof types.IntegerCompare) {
|
|
291
|
+
const value = obj;
|
|
292
|
+
if (typeof value !== "bigint" && typeof value !== "number") {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
return types.compare(value, f.compare, f.value.value);
|
|
296
|
+
}
|
|
297
|
+
else if (f instanceof types.BoolQuery) {
|
|
298
|
+
return obj === f.value; // true/false
|
|
299
|
+
}
|
|
300
|
+
logger.warn("Unsupported query type: " + f.constructor.name);
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
async handleQueryObject(f, value) {
|
|
304
|
+
if (f instanceof types.StateFieldQuery) {
|
|
305
|
+
return this.handleFieldQuery(f, value, 0);
|
|
306
|
+
}
|
|
307
|
+
else if (f instanceof types.Nested) {
|
|
308
|
+
// assume field valua is of array type and iterate over each object and match its parts
|
|
309
|
+
let arr = value[f.path];
|
|
310
|
+
if (!Array.isArray(arr)) {
|
|
311
|
+
throw new Error("Nested field is not an array");
|
|
312
|
+
}
|
|
313
|
+
for (const element of arr) {
|
|
314
|
+
for (const query of f.query) {
|
|
315
|
+
if (await this.handleQueryObject(query, element)) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return false; // TODO test this codepath
|
|
321
|
+
}
|
|
322
|
+
else if (f instanceof types.LogicalQuery) {
|
|
323
|
+
if (f instanceof types.And) {
|
|
324
|
+
for (const and of f.and) {
|
|
325
|
+
const ret = await this.handleQueryObject(and, value);
|
|
326
|
+
if (!ret) {
|
|
327
|
+
return ret;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
if (f instanceof types.Or) {
|
|
333
|
+
for (const or of f.or) {
|
|
334
|
+
const ret = await this.handleQueryObject(or, value);
|
|
335
|
+
if (ret === true) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
else if (ret === undefined) {
|
|
339
|
+
return undefined;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
if (f instanceof types.Not) {
|
|
345
|
+
const ret = await this.handleQueryObject(f.not, value);
|
|
346
|
+
if (ret === undefined) {
|
|
347
|
+
return undefined;
|
|
348
|
+
}
|
|
349
|
+
return !ret;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
logger.info("Unsupported query type: " + f.constructor.name);
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
handleStringMatch(f, compare, fv) {
|
|
356
|
+
if (typeof fv !== "string") {
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
if (f.caseInsensitive) {
|
|
360
|
+
fv = fv.toLowerCase();
|
|
361
|
+
}
|
|
362
|
+
if (f.method === types.StringMatchMethod.exact) {
|
|
363
|
+
return fv === compare;
|
|
364
|
+
}
|
|
365
|
+
if (f.method === types.StringMatchMethod.prefix) {
|
|
366
|
+
return fv.startsWith(compare);
|
|
367
|
+
}
|
|
368
|
+
if (f.method === types.StringMatchMethod.contains) {
|
|
369
|
+
return fv.includes(compare);
|
|
370
|
+
}
|
|
371
|
+
throw new Error("Unsupported");
|
|
372
|
+
}
|
|
373
|
+
async _queryDocuments(filter) {
|
|
374
|
+
// Whether we return the full operation data or just the db value
|
|
375
|
+
const results = [];
|
|
376
|
+
for (const value of this._index.values()) {
|
|
377
|
+
if (await filter(value)) {
|
|
378
|
+
results.push(value);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return results;
|
|
382
|
+
}
|
|
383
|
+
getPending(cursorId) {
|
|
384
|
+
return this._resultsCollectQueue.get(cursorId)?.arr.length;
|
|
385
|
+
}
|
|
386
|
+
get cursorCount() {
|
|
387
|
+
return this._resultsCollectQueue.size;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
export class HashmapIndices {
|
|
391
|
+
scopes;
|
|
392
|
+
indices = [];
|
|
393
|
+
closed;
|
|
394
|
+
constructor() {
|
|
395
|
+
this.scopes = new Map();
|
|
396
|
+
this.closed = true;
|
|
397
|
+
}
|
|
398
|
+
async init(properties) {
|
|
399
|
+
const existingIndex = this.indices.find((i) => i.schema === properties.schema);
|
|
400
|
+
if (existingIndex) {
|
|
401
|
+
return existingIndex.index;
|
|
402
|
+
}
|
|
403
|
+
const index = new HashmapIndex();
|
|
404
|
+
this.indices.push({ schema: properties.schema, index });
|
|
405
|
+
await index.init(properties);
|
|
406
|
+
if (!this.closed) {
|
|
407
|
+
await index.start();
|
|
408
|
+
}
|
|
409
|
+
return index;
|
|
410
|
+
}
|
|
411
|
+
async scope(name) {
|
|
412
|
+
let scope = this.scopes.get(name);
|
|
413
|
+
if (!scope) {
|
|
414
|
+
scope = new HashmapIndices();
|
|
415
|
+
if (!this.closed) {
|
|
416
|
+
await scope.start();
|
|
417
|
+
}
|
|
418
|
+
this.scopes.set(name, scope);
|
|
419
|
+
}
|
|
420
|
+
return scope;
|
|
421
|
+
}
|
|
422
|
+
async start() {
|
|
423
|
+
this.closed = false;
|
|
424
|
+
for (const scope of this.scopes.values()) {
|
|
425
|
+
await scope.start();
|
|
426
|
+
}
|
|
427
|
+
for (const index of this.indices) {
|
|
428
|
+
await index.index.start();
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
async stop() {
|
|
432
|
+
this.closed = true;
|
|
433
|
+
for (const scope of this.scopes.values()) {
|
|
434
|
+
await scope.stop();
|
|
435
|
+
}
|
|
436
|
+
for (const index of this.indices) {
|
|
437
|
+
await index.index.stop();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
async drop() {
|
|
441
|
+
for (const scope of this.scopes.values()) {
|
|
442
|
+
await scope.drop();
|
|
443
|
+
}
|
|
444
|
+
for (const index of this.indices) {
|
|
445
|
+
await index.index.drop();
|
|
446
|
+
}
|
|
447
|
+
this.scopes.clear();
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
const create = () => new HashmapIndices();
|
|
451
|
+
export { create };
|
|
452
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@peerbit/indexer-simple",
|
|
3
|
+
"version": "0.0.1-cccc078",
|
|
4
|
+
"description": "Simple in memory index for document store",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"types": "./dist/src/index.d.ts",
|
|
8
|
+
"typesVersions": {
|
|
9
|
+
"*": {
|
|
10
|
+
"*": [
|
|
11
|
+
"*",
|
|
12
|
+
"dist/*",
|
|
13
|
+
"dist/src/*",
|
|
14
|
+
"dist/src/*/index"
|
|
15
|
+
],
|
|
16
|
+
"src/*": [
|
|
17
|
+
"*",
|
|
18
|
+
"dist/*",
|
|
19
|
+
"dist/src/*",
|
|
20
|
+
"dist/src/*/index"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"src",
|
|
26
|
+
"dist",
|
|
27
|
+
"!dist/e2e",
|
|
28
|
+
"!dist/test",
|
|
29
|
+
"!**/*.tsbuildinfo"
|
|
30
|
+
],
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/src/index.d.ts",
|
|
34
|
+
"import": "./dist/src/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"eslintConfig": {
|
|
38
|
+
"extends": "peerbit",
|
|
39
|
+
"parserOptions": {
|
|
40
|
+
"project": true,
|
|
41
|
+
"sourceType": "module"
|
|
42
|
+
},
|
|
43
|
+
"ignorePatterns": [
|
|
44
|
+
"!.aegir.js",
|
|
45
|
+
"test/ts-use",
|
|
46
|
+
"*.d.ts"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"clean": "aegir clean",
|
|
54
|
+
"build": "aegir build --no-bundle",
|
|
55
|
+
"test": "aegir test",
|
|
56
|
+
"lint": "aegir lint"
|
|
57
|
+
},
|
|
58
|
+
"author": "dao.xyz",
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@peerbit/indexer-interface": "0.0.1-cccc078"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@peerbit/indexer-tests": "0.0.1-cccc078"
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import { deserialize, serialize } from "@dao-xyz/borsh";
|
|
2
|
+
import { Cache } from "@peerbit/cache";
|
|
3
|
+
import * as types from "@peerbit/indexer-interface";
|
|
4
|
+
import { logger as loggerFn } from "@peerbit/logger";
|
|
5
|
+
import { equals } from "uint8arrays";
|
|
6
|
+
|
|
7
|
+
const logger = loggerFn({ module: "simple-index-engine" });
|
|
8
|
+
|
|
9
|
+
const getBatchFromResults = <T extends Record<string, any>>(
|
|
10
|
+
results: types.IndexedValue<T>[],
|
|
11
|
+
wantedSize: number,
|
|
12
|
+
/* properties: types.IteratorBatchProperties */
|
|
13
|
+
) => {
|
|
14
|
+
const batch: types.IndexedValue<T>[] = [];
|
|
15
|
+
/* let size = 0; */
|
|
16
|
+
for (const result of results) {
|
|
17
|
+
batch.push(result);
|
|
18
|
+
/* size += types.extractFieldValue<number>(result, properties.sizeProperty);
|
|
19
|
+
if (size > properties.maxSize) {
|
|
20
|
+
break;
|
|
21
|
+
} */
|
|
22
|
+
if (wantedSize <= batch.length) {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
results.splice(0, batch.length);
|
|
27
|
+
return batch;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/* const resolveNestedAliasesRecursively = (request: types.SearchRequest) => {
|
|
31
|
+
const map = new Map();
|
|
32
|
+
for (const query of request.query) {
|
|
33
|
+
_resolveNestedAliasesRecursively(query, map);
|
|
34
|
+
}
|
|
35
|
+
return map;
|
|
36
|
+
}
|
|
37
|
+
*/
|
|
38
|
+
const cloneResults = <T>(
|
|
39
|
+
indexed: types.IndexedValue<T>[],
|
|
40
|
+
schema: any,
|
|
41
|
+
): types.IndexedValue<T>[] => {
|
|
42
|
+
return indexed.map((x) => {
|
|
43
|
+
return { id: x.id, value: deserialize(serialize(x.value), schema) };
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
/*
|
|
47
|
+
const _resolveNestedAliasesRecursively = (query: types.Query, aliases: Map<string, string>) => {
|
|
48
|
+
|
|
49
|
+
if (query instanceof types.Nested) {
|
|
50
|
+
aliases.set(query.id, query.path);
|
|
51
|
+
for (const subQuery of query.query) {
|
|
52
|
+
_resolveNestedAliasesRecursively(subQuery, aliases);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (query instanceof types.And) {
|
|
56
|
+
for (const subQuery of query.and) {
|
|
57
|
+
_resolveNestedAliasesRecursively(subQuery, aliases);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (query instanceof types.Or) {
|
|
61
|
+
for (const subQuery of query.or) {
|
|
62
|
+
_resolveNestedAliasesRecursively(subQuery, aliases);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (query instanceof types.Not) {
|
|
66
|
+
_resolveNestedAliasesRecursively(query.not, aliases);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
export class HashmapIndex<T extends Record<string, any>, NestedType = any>
|
|
73
|
+
implements types.Index<T, NestedType>
|
|
74
|
+
{
|
|
75
|
+
private _index: Map<string | bigint | number, types.IndexedValue<T>>;
|
|
76
|
+
private _resultsCollectQueue: Cache<{
|
|
77
|
+
arr: types.IndexedValue<T>[];
|
|
78
|
+
reference: boolean | undefined;
|
|
79
|
+
}>;
|
|
80
|
+
|
|
81
|
+
private indexByArr: string[];
|
|
82
|
+
private properties: types.IndexEngineInitProperties<T, NestedType>;
|
|
83
|
+
|
|
84
|
+
init(properties: types.IndexEngineInitProperties<T, NestedType>) {
|
|
85
|
+
this.properties = properties;
|
|
86
|
+
this._index = new Map();
|
|
87
|
+
this._resultsCollectQueue = new Cache({ max: 10000 }); // TODO choose limit better
|
|
88
|
+
if (properties.indexBy) {
|
|
89
|
+
this.indexByArr = Array.isArray(properties.indexBy)
|
|
90
|
+
? properties.indexBy
|
|
91
|
+
: [properties.indexBy];
|
|
92
|
+
} else {
|
|
93
|
+
const indexBy = types.getIdProperty(properties.schema);
|
|
94
|
+
|
|
95
|
+
if (!indexBy) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"No indexBy property defined nor schema has a property decorated with `id({ type: '...' })`",
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.indexByArr = indexBy;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async get(id: types.IdKey): Promise<types.IndexedResult<T> | undefined> {
|
|
108
|
+
const value = this._index.get(id.primitive);
|
|
109
|
+
if (!value) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
id,
|
|
114
|
+
value: value.value,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
put(
|
|
119
|
+
value: T,
|
|
120
|
+
id = types.toId(types.extractFieldValue(value, this.indexByArr)),
|
|
121
|
+
): void {
|
|
122
|
+
this._index.set(id.primitive, { id, value });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async del(query: types.DeleteRequest): Promise<types.IdKey[]> {
|
|
126
|
+
let deleted: types.IdKey[] = [];
|
|
127
|
+
for (const doc of await this.queryAll(query)) {
|
|
128
|
+
if (this._index.delete(doc.id.primitive)) {
|
|
129
|
+
deleted.push(doc.id);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return deleted;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
getSize(): number | Promise<number> {
|
|
136
|
+
return this._index.size;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
iterator() {
|
|
140
|
+
// return a iterator if key value pairs, where the value is the indexed record
|
|
141
|
+
return this._index.entries();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
start(): void | Promise<void> {
|
|
145
|
+
// nothing to do
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
stop(): void | Promise<void> {
|
|
149
|
+
this._resultsCollectQueue.clear();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
drop() {
|
|
153
|
+
this._index.clear();
|
|
154
|
+
this._resultsCollectQueue.clear();
|
|
155
|
+
/* for (const subindex of this.subIndices) {
|
|
156
|
+
subindex[1].clear()
|
|
157
|
+
} */
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/* subindex(name: string): types.IndexEngine<any> {
|
|
161
|
+
|
|
162
|
+
const subIndex = new HashmapIndexEngine();
|
|
163
|
+
this.subIndices.set(name, subIndex);
|
|
164
|
+
return subIndex;
|
|
165
|
+
}
|
|
166
|
+
*/
|
|
167
|
+
|
|
168
|
+
async sum(query: types.SumRequest): Promise<number | bigint> {
|
|
169
|
+
let sum: undefined | number | bigint = undefined;
|
|
170
|
+
for (const doc of await this.queryAll(query)) {
|
|
171
|
+
let value: any = doc.value;
|
|
172
|
+
for (const path of query.key) {
|
|
173
|
+
value = value[path];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (typeof value === "number") {
|
|
177
|
+
sum = ((sum as number) || 0) + value;
|
|
178
|
+
} else if (typeof value === "bigint") {
|
|
179
|
+
sum = ((sum as bigint) || 0n) + value;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return sum != null ? sum : 0;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async count(query: types.CountRequest): Promise<number> {
|
|
186
|
+
return (await this.queryAll(query)).length;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private async queryAll(
|
|
190
|
+
query:
|
|
191
|
+
| types.SearchRequest
|
|
192
|
+
| types.DeleteRequest
|
|
193
|
+
| types.CountRequest
|
|
194
|
+
| types.SumRequest,
|
|
195
|
+
): Promise<types.IndexedValue<T>[]> {
|
|
196
|
+
if (
|
|
197
|
+
query.query.length === 1 &&
|
|
198
|
+
(query.query[0] instanceof types.ByteMatchQuery ||
|
|
199
|
+
query.query[0] instanceof types.StringMatch) &&
|
|
200
|
+
types.stringArraysEquals(query.query[0].key, this.indexByArr)
|
|
201
|
+
) {
|
|
202
|
+
const firstQuery = query.query[0];
|
|
203
|
+
if (firstQuery instanceof types.ByteMatchQuery) {
|
|
204
|
+
const doc = this._index.get(types.toId(firstQuery.value).primitive);
|
|
205
|
+
return doc ? [doc] : [];
|
|
206
|
+
} else if (
|
|
207
|
+
firstQuery instanceof types.StringMatch &&
|
|
208
|
+
firstQuery.method === types.StringMatchMethod.exact &&
|
|
209
|
+
firstQuery.caseInsensitive === false
|
|
210
|
+
) {
|
|
211
|
+
const doc = this._index.get(firstQuery.value);
|
|
212
|
+
return doc ? [doc] : [];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Handle query normally
|
|
217
|
+
const indexedDocuments = await this._queryDocuments(async (doc) => {
|
|
218
|
+
for (const f of query.query) {
|
|
219
|
+
if (!(await this.handleQueryObject(f, doc.value))) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return true;
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
return indexedDocuments;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async query(
|
|
230
|
+
query: types.SearchRequest,
|
|
231
|
+
properties: { reference?: boolean },
|
|
232
|
+
): Promise<types.IndexedResults<T>> {
|
|
233
|
+
const indexedDocuments = await this.queryAll(query);
|
|
234
|
+
if (indexedDocuments.length <= 1) {
|
|
235
|
+
return {
|
|
236
|
+
kept: 0,
|
|
237
|
+
results: indexedDocuments,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* const aliases = resolveNestedAliasesRecursively(query) */
|
|
242
|
+
|
|
243
|
+
// Sort
|
|
244
|
+
indexedDocuments.sort((a, b) =>
|
|
245
|
+
types.extractSortCompare(a.value, b.value, query.sort),
|
|
246
|
+
);
|
|
247
|
+
const batch = getBatchFromResults<T>(
|
|
248
|
+
indexedDocuments,
|
|
249
|
+
query.fetch,
|
|
250
|
+
/* this.properties.iterator.batch, */
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
if (indexedDocuments.length > 0) {
|
|
254
|
+
this._resultsCollectQueue.add(query.idString, {
|
|
255
|
+
arr: indexedDocuments,
|
|
256
|
+
reference: properties?.reference,
|
|
257
|
+
}); // cache resulst not returned
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// TODO dont leak kept if canRead is defined, or return something random
|
|
261
|
+
return {
|
|
262
|
+
kept: indexedDocuments.length,
|
|
263
|
+
results: properties?.reference
|
|
264
|
+
? batch
|
|
265
|
+
: cloneResults(batch, this.properties.schema),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async next(
|
|
270
|
+
query: types.CollectNextRequest,
|
|
271
|
+
): Promise<types.IndexedResults<T>> {
|
|
272
|
+
const results = this._resultsCollectQueue.get(query.idString);
|
|
273
|
+
if (!results) {
|
|
274
|
+
return {
|
|
275
|
+
results: [],
|
|
276
|
+
kept: 0,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const batch = getBatchFromResults<T>(
|
|
281
|
+
results.arr,
|
|
282
|
+
query.amount,
|
|
283
|
+
/* this.properties.iterator.batch */
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
if (results.arr.length === 0) {
|
|
287
|
+
this._resultsCollectQueue.del(query.idString); // TODO add tests for proper cleanup/timeouts
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// TODO dont leak kept if canRead is defined, or return something random
|
|
291
|
+
return {
|
|
292
|
+
results: results.reference
|
|
293
|
+
? batch
|
|
294
|
+
: cloneResults(batch, this.properties.schema),
|
|
295
|
+
kept: results.arr.length,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
close(query: types.CloseIteratorRequest): void {
|
|
300
|
+
this._resultsCollectQueue.del(query.idString);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
private async handleFieldQuery(
|
|
304
|
+
f: types.StateFieldQuery,
|
|
305
|
+
obj: any,
|
|
306
|
+
startIndex: number,
|
|
307
|
+
): Promise<boolean | undefined> {
|
|
308
|
+
// this clause is needed if we have a field that is of type [][] (we will recursively go through each subarray)
|
|
309
|
+
|
|
310
|
+
if (
|
|
311
|
+
Array.isArray(obj) ||
|
|
312
|
+
(obj instanceof Uint8Array && f instanceof types.ByteMatchQuery === false)
|
|
313
|
+
) {
|
|
314
|
+
for (const element of obj) {
|
|
315
|
+
if (await this.handleFieldQuery(f, element, startIndex)) {
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Resolve the field from the key path. If we reach an array or nested Document store,
|
|
323
|
+
// then do a recursive call or a search to look into them
|
|
324
|
+
for (let i = startIndex; i < f.key.length; i++) {
|
|
325
|
+
obj = obj[f.key[i]];
|
|
326
|
+
if (
|
|
327
|
+
Array.isArray(obj) ||
|
|
328
|
+
(obj instanceof Uint8Array &&
|
|
329
|
+
f instanceof types.ByteMatchQuery === false)
|
|
330
|
+
) {
|
|
331
|
+
for (const element of obj) {
|
|
332
|
+
if (await this.handleFieldQuery(f, element, i + 1)) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
if (this.properties.nested?.match(obj)) {
|
|
339
|
+
const queryCloned = f.clone();
|
|
340
|
+
queryCloned.key.splice(0, i + 1); // remove key path until the document store
|
|
341
|
+
const results = await this.properties.nested.query(
|
|
342
|
+
obj,
|
|
343
|
+
new types.SearchRequest({ query: [queryCloned] }),
|
|
344
|
+
);
|
|
345
|
+
return results.length > 0 ? true : false; // TODO return INNER HITS?
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (f instanceof types.IsNull) {
|
|
350
|
+
if (obj == null) {
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (obj == null) {
|
|
357
|
+
return undefined;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// When we reach here, the field value (obj) is comparable
|
|
361
|
+
if (f instanceof types.StringMatch) {
|
|
362
|
+
let compare = f.value;
|
|
363
|
+
if (f.caseInsensitive) {
|
|
364
|
+
compare = compare.toLowerCase();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (this.handleStringMatch(f, compare, obj)) {
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
} else if (f instanceof types.ByteMatchQuery) {
|
|
372
|
+
if (obj instanceof Uint8Array === false) {
|
|
373
|
+
if (types.stringArraysEquals(f.key, this.indexByArr)) {
|
|
374
|
+
return f.valueString === obj;
|
|
375
|
+
}
|
|
376
|
+
return false;
|
|
377
|
+
}
|
|
378
|
+
return equals(obj as Uint8Array, f.value);
|
|
379
|
+
} else if (f instanceof types.IntegerCompare) {
|
|
380
|
+
const value: bigint | number = obj as any as bigint | number;
|
|
381
|
+
|
|
382
|
+
if (typeof value !== "bigint" && typeof value !== "number") {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
return types.compare(value, f.compare, f.value.value);
|
|
386
|
+
} else if (f instanceof types.BoolQuery) {
|
|
387
|
+
return obj === f.value; // true/false
|
|
388
|
+
}
|
|
389
|
+
logger.warn("Unsupported query type: " + f.constructor.name);
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
private async handleQueryObject(
|
|
394
|
+
f: types.Query,
|
|
395
|
+
value: Record<string, any> | T,
|
|
396
|
+
): Promise<boolean | undefined> {
|
|
397
|
+
if (f instanceof types.StateFieldQuery) {
|
|
398
|
+
return this.handleFieldQuery(f, value as T, 0);
|
|
399
|
+
} else if (f instanceof types.Nested) {
|
|
400
|
+
// assume field valua is of array type and iterate over each object and match its parts
|
|
401
|
+
let arr = value[f.path];
|
|
402
|
+
if (!Array.isArray(arr)) {
|
|
403
|
+
throw new Error("Nested field is not an array");
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
for (const element of arr) {
|
|
407
|
+
for (const query of f.query) {
|
|
408
|
+
if (await this.handleQueryObject(query, element)) {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return false; // TODO test this codepath
|
|
414
|
+
} else if (f instanceof types.LogicalQuery) {
|
|
415
|
+
if (f instanceof types.And) {
|
|
416
|
+
for (const and of f.and) {
|
|
417
|
+
const ret = await this.handleQueryObject(and, value);
|
|
418
|
+
if (!ret) {
|
|
419
|
+
return ret;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return true;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (f instanceof types.Or) {
|
|
426
|
+
for (const or of f.or) {
|
|
427
|
+
const ret = await this.handleQueryObject(or, value);
|
|
428
|
+
if (ret === true) {
|
|
429
|
+
return true;
|
|
430
|
+
} else if (ret === undefined) {
|
|
431
|
+
return undefined;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
if (f instanceof types.Not) {
|
|
437
|
+
const ret = await this.handleQueryObject(f.not, value);
|
|
438
|
+
if (ret === undefined) {
|
|
439
|
+
return undefined;
|
|
440
|
+
}
|
|
441
|
+
return !ret;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
logger.info("Unsupported query type: " + f.constructor.name);
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
private handleStringMatch(f: types.StringMatch, compare: string, fv: string) {
|
|
450
|
+
if (typeof fv !== "string") {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
if (f.caseInsensitive) {
|
|
454
|
+
fv = fv.toLowerCase();
|
|
455
|
+
}
|
|
456
|
+
if (f.method === types.StringMatchMethod.exact) {
|
|
457
|
+
return fv === compare;
|
|
458
|
+
}
|
|
459
|
+
if (f.method === types.StringMatchMethod.prefix) {
|
|
460
|
+
return fv.startsWith(compare);
|
|
461
|
+
}
|
|
462
|
+
if (f.method === types.StringMatchMethod.contains) {
|
|
463
|
+
return fv.includes(compare);
|
|
464
|
+
}
|
|
465
|
+
throw new Error("Unsupported");
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
private async _queryDocuments(
|
|
469
|
+
filter: (doc: types.IndexedValue) => Promise<boolean>,
|
|
470
|
+
): Promise<types.IndexedValue<T>[]> {
|
|
471
|
+
// Whether we return the full operation data or just the db value
|
|
472
|
+
const results: types.IndexedValue<T>[] = [];
|
|
473
|
+
for (const value of this._index.values()) {
|
|
474
|
+
if (await filter(value)) {
|
|
475
|
+
results.push(value);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return results;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
getPending(cursorId: string): number | undefined {
|
|
482
|
+
return this._resultsCollectQueue.get(cursorId)?.arr.length;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
get cursorCount(): number {
|
|
486
|
+
return this._resultsCollectQueue.size;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
export class HashmapIndices implements types.Indices {
|
|
491
|
+
private scopes: Map<string, types.Indices>;
|
|
492
|
+
private indices: { schema: any; index: HashmapIndex<any, any> }[] = [];
|
|
493
|
+
private closed: boolean;
|
|
494
|
+
constructor() {
|
|
495
|
+
this.scopes = new Map();
|
|
496
|
+
this.closed = true;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
async init<T extends Record<string, any>, NestedType>(
|
|
500
|
+
properties: types.IndexEngineInitProperties<T, any>,
|
|
501
|
+
) {
|
|
502
|
+
const existingIndex = this.indices.find(
|
|
503
|
+
(i) => i.schema === properties.schema,
|
|
504
|
+
);
|
|
505
|
+
if (existingIndex) {
|
|
506
|
+
return existingIndex.index as HashmapIndex<T, NestedType>;
|
|
507
|
+
}
|
|
508
|
+
const index = new HashmapIndex<T, NestedType>();
|
|
509
|
+
this.indices.push({ schema: properties.schema, index });
|
|
510
|
+
await index.init(properties);
|
|
511
|
+
|
|
512
|
+
if (!this.closed) {
|
|
513
|
+
await index.start();
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return index;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
async scope(name: string): Promise<types.Indices> {
|
|
520
|
+
let scope = this.scopes.get(name);
|
|
521
|
+
if (!scope) {
|
|
522
|
+
scope = new HashmapIndices();
|
|
523
|
+
if (!this.closed) {
|
|
524
|
+
await scope.start();
|
|
525
|
+
}
|
|
526
|
+
this.scopes.set(name, scope);
|
|
527
|
+
}
|
|
528
|
+
return scope;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
async start(): Promise<void> {
|
|
532
|
+
this.closed = false;
|
|
533
|
+
for (const scope of this.scopes.values()) {
|
|
534
|
+
await scope.start();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
for (const index of this.indices) {
|
|
538
|
+
await index.index.start();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
async stop(): Promise<void> {
|
|
543
|
+
this.closed = true;
|
|
544
|
+
for (const scope of this.scopes.values()) {
|
|
545
|
+
await scope.stop();
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
for (const index of this.indices) {
|
|
549
|
+
await index.index.stop();
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
async drop(): Promise<void> {
|
|
553
|
+
for (const scope of this.scopes.values()) {
|
|
554
|
+
await scope.drop();
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
for (const index of this.indices) {
|
|
558
|
+
await index.index.drop();
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
this.scopes.clear();
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const create = () => new HashmapIndices();
|
|
566
|
+
export { create };
|