datafolder 1.0.19 → 1.0.21

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.
@@ -0,0 +1,451 @@
1
+ import test from "node:test";
2
+ import { deepEqual } from "node:assert/strict";
3
+ import { QyDB } from "../src/QyDB.js";
4
+ import { logger } from "../src/QyLogger.js";
5
+ logger.level = "warn";
6
+ // FOR doc IN employees
7
+ // COLLECT department = doc.department
8
+ // AGGREGATE count = COUNT(doc)
9
+ // RETURN {department: department, employeeCount: count}
10
+ function query1(qyDB) {
11
+ deepEqual(Object.fromEntries(qyDB
12
+ .indexDir("employees", "department")
13
+ .fileList.map((file) => [file.name, Object.keys(file.fileContent).length])), { sales: 4, product: 2, "R&D": 2 });
14
+ }
15
+ // FOR doc IN employees
16
+ // LET isOlder = doc.age > 30
17
+ // LET isSales = doc.department == "sales"
18
+ // FILTER isOlder && isSales
19
+ // RETURN doc
20
+ function query2(qyDB) {
21
+ deepEqual(Object.fromEntries(qyDB.queryFiles("employees", { department: "sales", age: { $gt: 30 } }).map((x) => [x.name, x.view()])), {
22
+ employee_1_1: { age: 31, department: "sales" },
23
+ employee_1_5: { age: 36, department: "sales" },
24
+ employee_1_6: { age: 36, department: "sales" },
25
+ });
26
+ }
27
+ function query3(qyDB) {
28
+ deepEqual(Object.fromEntries(qyDB
29
+ .queryFiles("employees", { $and: [{ department: "sales" }, { $and: [{ age: { $gt: 30, $lt: 60 } }] }] })
30
+ .map((x) => [x.name, x.view()])), {
31
+ employee_1_1: { age: 31, department: "sales" },
32
+ employee_1_5: { age: 36, department: "sales" },
33
+ employee_1_6: { age: 36, department: "sales" },
34
+ });
35
+ }
36
+ function query4(qyDB) {
37
+ const result = {};
38
+ qyDB.fetch
39
+ .cd("employees")
40
+ .queryFiles(".", { department: "sales", age: { $gt: 30 } })
41
+ .run()[0]
42
+ .forEach((x) => (result[x.name] = x.view()));
43
+ deepEqual(result, {
44
+ employee_1_1: { age: 31, department: "sales" },
45
+ employee_1_5: { age: 36, department: "sales" },
46
+ employee_1_6: { age: 36, department: "sales" },
47
+ });
48
+ }
49
+ function query5(qyDB) {
50
+ const result = {};
51
+ qyDB.fetch
52
+ .queryFiles("employees", {
53
+ department: (x) => x == "sales",
54
+ age: (x) => x > 30,
55
+ })
56
+ .run()[0]
57
+ .forEach((x) => (result[x.name] = x.view()));
58
+ deepEqual(result, {
59
+ employee_1_1: { age: 31, department: "sales" },
60
+ employee_1_5: { age: 36, department: "sales" },
61
+ employee_1_6: { age: 36, department: "sales" },
62
+ });
63
+ }
64
+ function query6(qyDB) {
65
+ const result = qyDB
66
+ .queryFiles("employees", {
67
+ department: (x) => x != "sales",
68
+ age: (x) => x > 30,
69
+ })
70
+ .reduce((map, x) => {
71
+ map[x.name] = x.view();
72
+ return map;
73
+ }, {});
74
+ deepEqual(result, {
75
+ employee_1_9: { age: 46, department: "R&D" },
76
+ employee_1_2: { age: 38, department: "product" },
77
+ employee_1_7: { age: 36, department: "product" },
78
+ });
79
+ }
80
+ function query7(qyDB) {
81
+ const result = {};
82
+ const queryObj = {
83
+ department: (x) => x == "sales",
84
+ age: (x) => x > 30,
85
+ };
86
+ ["employees", "employees/*/*"].forEach((folderPath) => {
87
+ qyDB.fetch
88
+ .queryFiles(folderPath, queryObj)
89
+ .run()[0]
90
+ .forEach((x) => (result[x.fullPath] = x.view()));
91
+ });
92
+ deepEqual(result, {
93
+ "/employees/2024/12/employee_3_1": { department: "sales", age: 31 },
94
+ "/employees/2025/03/employee_2_1": { department: "sales", age: 31 },
95
+ "/employees/employee_1_1": { department: "sales", age: 31 },
96
+ "/employees/2024/12/employee_3_5": { department: "sales", age: 36 },
97
+ "/employees/2025/03/employee_2_5": { department: "sales", age: 36 },
98
+ "/employees/employee_1_5": { department: "sales", age: 36 },
99
+ "/employees/2024/12/employee_3_6": { department: "sales", age: 36 },
100
+ "/employees/2025/03/employee_2_6": { department: "sales", age: 36 },
101
+ "/employees/employee_1_6": { department: "sales", age: 36 },
102
+ });
103
+ }
104
+ function query8(qyDB) {
105
+ const result = ["employees", ["employees", "*", "*"]]
106
+ .map((folderPath) => qyDB.queryFiles(folderPath, {
107
+ department: (x) => x != "sales",
108
+ age: (x) => x > 30,
109
+ }))
110
+ .flat()
111
+ .reduce((map, x) => {
112
+ map[x.fullPath] = x.view();
113
+ return map;
114
+ }, {});
115
+ deepEqual(result, {
116
+ "/employees/2024/12/employee_3_2": { department: "product", age: 38 },
117
+ "/employees/2025/03/employee_2_2": { department: "product", age: 38 },
118
+ "/employees/employee_1_2": { department: "product", age: 38 },
119
+ "/employees/2024/12/employee_3_7": { department: "product", age: 36 },
120
+ "/employees/2025/03/employee_2_7": { department: "product", age: 36 },
121
+ "/employees/employee_1_7": { department: "product", age: 36 },
122
+ "/employees/2024/12/employee_3_9": { department: "R&D", age: 46 },
123
+ "/employees/2025/03/employee_2_9": { department: "R&D", age: 46 },
124
+ "/employees/employee_1_9": { department: "R&D", age: 46 },
125
+ });
126
+ }
127
+ function query9(qyDB) {
128
+ const queryObj = { $and: [{ department: (x) => x != "sales" }, { age: (x) => x > 30 }] };
129
+ deepEqual(qyDB.fetch
130
+ .cd("employees")
131
+ .queryFiles("2024/12", queryObj)
132
+ .queryFiles("2025/03", queryObj)
133
+ .queryFiles(".", queryObj)
134
+ .run()
135
+ .map((list) => list.reduce((map, x) => {
136
+ map[x.fullPath] = x.view();
137
+ return map;
138
+ }, {})), [
139
+ {
140
+ "/employees/2024/12/employee_3_2": { department: "product", age: 38 },
141
+ "/employees/2024/12/employee_3_7": { department: "product", age: 36 },
142
+ "/employees/2024/12/employee_3_9": { department: "R&D", age: 46 },
143
+ },
144
+ {
145
+ "/employees/2025/03/employee_2_2": { department: "product", age: 38 },
146
+ "/employees/2025/03/employee_2_7": { department: "product", age: 36 },
147
+ "/employees/2025/03/employee_2_9": { department: "R&D", age: 46 },
148
+ },
149
+ {
150
+ "/employees/employee_1_2": { department: "product", age: 38 },
151
+ "/employees/employee_1_7": { department: "product", age: 36 },
152
+ "/employees/employee_1_9": { department: "R&D", age: 46 },
153
+ },
154
+ ]);
155
+ }
156
+ function query10(qyDB) {
157
+ const queryObj = {
158
+ $or: [{ department: (x) => x != "sales", age: (x) => x > 36 }, { age: (x) => x > 40 }],
159
+ };
160
+ deepEqual(qyDB.fetch
161
+ .cd("employees")
162
+ .queryFiles("*/*", queryObj)
163
+ .queryFiles(".", queryObj)
164
+ .run()
165
+ .map((list) => list.reduce((map, x) => {
166
+ map[x.fullPath] = x.view();
167
+ return map;
168
+ }, {})), [
169
+ {
170
+ "/employees/2024/12/employee_3_2": { department: "product", age: 38 },
171
+ "/employees/2024/12/employee_3_9": { department: "R&D", age: 46 },
172
+ "/employees/2025/03/employee_2_2": { department: "product", age: 38 },
173
+ "/employees/2025/03/employee_2_9": { department: "R&D", age: 46 },
174
+ },
175
+ {
176
+ "/employees/employee_1_2": { department: "product", age: 38 },
177
+ "/employees/employee_1_9": { department: "R&D", age: 46 },
178
+ },
179
+ ]);
180
+ }
181
+ function query11(qyDB) {
182
+ const queryObj = {
183
+ $and: [
184
+ {
185
+ $or: [{ department: (x) => x != "sales", age: (x) => x > 36 }],
186
+ },
187
+ { age: (x) => x > 40 },
188
+ ],
189
+ };
190
+ deepEqual(qyDB.fetch
191
+ .cd("employees")
192
+ .queryFiles("*/*", queryObj)
193
+ .queryFiles(".", queryObj)
194
+ .run()
195
+ .map((list) => list.reduce((map, x) => {
196
+ map[x.fullPath] = x.view();
197
+ return map;
198
+ }, {})), [
199
+ {
200
+ "/employees/2024/12/employee_3_9": { department: "R&D", age: 46 },
201
+ "/employees/2025/03/employee_2_9": { department: "R&D", age: 46 },
202
+ },
203
+ { "/employees/employee_1_9": { department: "R&D", age: 46 } },
204
+ ]);
205
+ }
206
+ function query12(qyDB) {
207
+ const queryObj = {
208
+ $and: { department: (x) => x != "sales", age: (x) => x > 36 },
209
+ age: (x) => x > 40,
210
+ };
211
+ deepEqual(qyDB.fetch
212
+ .cd("employees")
213
+ .queryFiles([(x) => x >= 2024 && x <= 2025, (x) => x != 10], queryObj, 2)
214
+ .queryFiles(".", queryObj, 2)
215
+ .run()
216
+ .map((list) => list.reduce((map, x) => {
217
+ map[x.fullPath] = x.view();
218
+ return map;
219
+ }, {})), [
220
+ {
221
+ "/employees/2024/12/employee_3_9": { department: "R&D", age: 46 },
222
+ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" },
223
+ },
224
+ { "/employees/employee_1_9": { department: "R&D", age: 46 } },
225
+ ]);
226
+ }
227
+ function query13(qyDB) {
228
+ const queryObj = { $and: { department: (x) => x != "sales", age: (x) => x > 36 }, age: (x) => x > 40 };
229
+ deepEqual(qyDB.fetch
230
+ .cd("employees")
231
+ .queryFiles([(x) => x >= 2024 && x <= 2025, (x) => x != 10], queryObj, 1)
232
+ .queryFiles(".", queryObj, 1)
233
+ .run()
234
+ .map((list) => list.reduce((map, x) => {
235
+ map[x.fullPath] = x.view();
236
+ return map;
237
+ }, {})), [
238
+ { "/employees/2024/12/employee_3_9": { department: "R&D", age: 46 } },
239
+ { "/employees/employee_1_9": { department: "R&D", age: 46 } },
240
+ ]);
241
+ }
242
+ function query14(qyDB) {
243
+ const queryObj = { $and: { department: (x) => x != "sales", age: (x) => x > 36 }, age: (x) => x > 40 };
244
+ deepEqual(qyDB.fetch
245
+ .cd("employees")
246
+ .queryFiles([(x) => x >= 2024 && x <= 2025, (x) => x != 10], queryObj, 1, 1)
247
+ .queryFiles(".", queryObj, 1, 1)
248
+ .run()
249
+ .map((list) => list.reduce((map, x) => {
250
+ map[x.fullPath] = x.view();
251
+ return map;
252
+ }, {})), [{ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" } }, {}]);
253
+ deepEqual(qyDB.fetch
254
+ .cd("employees")
255
+ .queryFiles([{ $gte: 2024, $lte: 2025 }, (x) => x != 10], queryObj, 1, 1)
256
+ .queryFiles(".", queryObj, 1, 1)
257
+ .run()
258
+ .map((list) => list.reduce((map, x) => {
259
+ map[x.fullPath] = x.view();
260
+ return map;
261
+ }, {})), [{ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" } }, {}]);
262
+ deepEqual(qyDB.fetch
263
+ .cd("employees")
264
+ .queryFiles([{ $gt: 2023, $gte: 2024, $lte: 2025, $lt: 2026 }, (x) => x != 10], queryObj, 1, 1)
265
+ .queryFiles(".", queryObj, 1, 1)
266
+ .run()
267
+ .map((list) => list.reduce((map, x) => {
268
+ map[x.fullPath] = x.view();
269
+ return map;
270
+ }, {})), [{ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" } }, {}]);
271
+ deepEqual(qyDB.fetch
272
+ .cd("employees")
273
+ .queryFiles([{ $gt: 2023, $gte: 2024, $lte: 2025, $lt: 2025 }, (x) => x != 10], queryObj, 1, 1)
274
+ .queryFiles(".", queryObj, 1, 1)
275
+ .run(), [[], []]);
276
+ deepEqual(qyDB.fetch
277
+ .cd("employees")
278
+ .queryFiles([{ $gt: 2024, $gte: 2024, $lte: 2025, $lt: 2026 }, (x) => x != 10], queryObj, 1, 1)
279
+ .queryFiles(".", queryObj, 1, 1)
280
+ .run(), [[], []]);
281
+ deepEqual(qyDB.fetch
282
+ .cd("employees")
283
+ .queryFiles([{ $or: [2024, 2025] }, (x) => x != 10], queryObj, 1, 1)
284
+ .queryFiles(".", queryObj, 1, 1)
285
+ .run()
286
+ .map((list) => list.reduce((map, x) => {
287
+ map[x.fullPath] = x.view();
288
+ return map;
289
+ }, {})), [{ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" } }, {}]);
290
+ deepEqual(qyDB.fetch
291
+ .cd("employees")
292
+ .queryFiles([{ $in: [2023, 2024, 2025] }, (x) => x != 10], queryObj, 1, 1)
293
+ .queryFiles(".", queryObj, 1, 1)
294
+ .run()
295
+ .map((list) => list.reduce((map, x) => {
296
+ map[x.fullPath] = x.view();
297
+ return map;
298
+ }, {})), [{ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" } }, {}]);
299
+ }
300
+ function query15(qyDB) {
301
+ const queryObj = { $and: { department: (x) => x != "sales", age: (x) => x > 36 }, age: (x) => x > 40 };
302
+ deepEqual(qyDB.fetch
303
+ .cd("employees")
304
+ .queryFiles({
305
+ $or: [".", [(x) => x >= 2024 && x <= 2025, (x) => x != 10]],
306
+ }, queryObj, 10, 0)
307
+ .run()
308
+ .map((list) => list.reduce((map, x) => {
309
+ map[x.fullPath] = x.view();
310
+ return map;
311
+ }, {})), [
312
+ {
313
+ "/employees/2024/12/employee_3_9": { age: 46, department: "R&D" },
314
+ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" },
315
+ "/employees/employee_1_9": { age: 46, department: "R&D" },
316
+ },
317
+ ]);
318
+ }
319
+ function query16(qyDB) {
320
+ const queryObj = {
321
+ $and: { department: (x) => x != "sales", age: (x) => x > 36 },
322
+ age: (x) => x > 40,
323
+ };
324
+ deepEqual(qyDB.fetch
325
+ .cd("employees")
326
+ .queryFilesMulti([["./**", queryObj]])
327
+ .run()
328
+ .map((list) => list.reduce((map, x) => {
329
+ map[x.fullPath] = x.view();
330
+ return map;
331
+ }, {})), [
332
+ {
333
+ "/employees/2025/03/employee_2_9": { age: 46, department: "R&D" },
334
+ "/employees/2024/12/employee_3_9": { age: 46, department: "R&D" },
335
+ "/employees/employee_1_9": { age: 46, department: "R&D" },
336
+ },
337
+ ]);
338
+ deepEqual(qyDB.fetch
339
+ .cd("employees")
340
+ .queryFilesMulti([["./**", queryObj]], 1, 1)
341
+ .run()
342
+ .map((list) => list.reduce((map, x) => {
343
+ map[x.fullPath] = x.view();
344
+ return map;
345
+ }, {})), [{ "/employees/2024/12/employee_3_9": { age: 46, department: "R&D" } }]);
346
+ }
347
+ function query17(qyDB) {
348
+ const result = {};
349
+ qyDB.fetch
350
+ .queryFiles("employees", {
351
+ department: { $or: ["sales", "R&D", "UNEXISTED"] },
352
+ age: (x) => x > 30,
353
+ })
354
+ .run()[0]
355
+ .forEach((x) => (result[x.name] = x.view()));
356
+ deepEqual(result, {
357
+ employee_1_1: { age: 31, department: "sales" },
358
+ employee_1_5: { age: 36, department: "sales" },
359
+ employee_1_6: { age: 36, department: "sales" },
360
+ employee_1_9: { age: 46, department: "R&D" },
361
+ });
362
+ }
363
+ function query18(qyDB) {
364
+ const result = {};
365
+ qyDB.fetch
366
+ .queryFiles("employees", "employee_1_1")
367
+ .run()[0]
368
+ .forEach((x) => (result[x.name] = x.view()));
369
+ deepEqual(result, {
370
+ employee_1_1: { age: 31, department: "sales" },
371
+ });
372
+ const result2 = {};
373
+ qyDB.queryFiles("**", "employee_1_1").forEach((x) => (result2[x.name] = x.view()));
374
+ deepEqual(result2, {
375
+ employee_1_1: { age: 31, department: "sales" },
376
+ });
377
+ }
378
+ function query19(qyDB) {
379
+ const result = {};
380
+ qyDB.fetch
381
+ .cd("employees")
382
+ .queryFiles("**", "employee_3_2")
383
+ .run()[0]
384
+ .forEach((x) => (result[x.name] = x.view()));
385
+ deepEqual(result, {
386
+ employee_3_2: { age: 38, department: "product" },
387
+ });
388
+ const result2 = {};
389
+ qyDB.queryFiles("**", "employee_2_1").forEach((x) => (result2[x.name] = x.view()));
390
+ deepEqual(result2, {
391
+ employee_2_1: { age: 31, department: "sales" },
392
+ });
393
+ }
394
+ let count = 0;
395
+ function getEmployeeData() {
396
+ ++count;
397
+ return {
398
+ [`employee_${count}_1`]: { department: "sales", age: 31 },
399
+ [`employee_${count}_2`]: { department: "product", age: 38 },
400
+ [`employee_${count}_3`]: { department: "R&D", age: 26 },
401
+ [`employee_${count}_4`]: { department: "sales", age: 25 },
402
+ [`employee_${count}_5`]: { department: "sales", age: 36 },
403
+ [`employee_${count}_6`]: { department: "sales", age: 36 },
404
+ [`employee_${count}_7`]: { department: "product", age: 36 },
405
+ [`employee_${count}_9`]: { department: "R&D", age: 46 },
406
+ };
407
+ }
408
+ function insertData(qyDB, dirPath) {
409
+ const { batch } = qyDB;
410
+ batch.cd(dirPath);
411
+ const employeeData = getEmployeeData();
412
+ for (const key in employeeData) {
413
+ batch.insert(key, employeeData[key]);
414
+ }
415
+ batch.run();
416
+ }
417
+ test("test QyAQL", { skip: false }, async (context) => {
418
+ context.after(async (t) => {
419
+ await qyDB.stop();
420
+ });
421
+ const dataFolder = "./tmp/QyAQL/1";
422
+ const qyDB = new QyDB(dataFolder, {});
423
+ await qyDB.start();
424
+ qyDB.delDir("employees");
425
+ qyDB.createIndex("employees", "department");
426
+ insertData(qyDB, "employees");
427
+ query1(qyDB);
428
+ insertData(qyDB, ["employees", "2025", "03"]);
429
+ insertData(qyDB, ["employees", "2024", "12"]);
430
+ await qyDB.stop();
431
+ await qyDB.start();
432
+ query1(qyDB);
433
+ query2(qyDB);
434
+ query3(qyDB);
435
+ query4(qyDB);
436
+ query5(qyDB);
437
+ query6(qyDB);
438
+ query7(qyDB);
439
+ query8(qyDB);
440
+ query9(qyDB);
441
+ query10(qyDB);
442
+ query11(qyDB);
443
+ query12(qyDB);
444
+ query13(qyDB);
445
+ query14(qyDB);
446
+ query15(qyDB);
447
+ query16(qyDB);
448
+ query17(qyDB);
449
+ query18(qyDB);
450
+ query19(qyDB);
451
+ });