document-dataply 0.0.4-alpha.5 → 0.0.4
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/cjs/index.js +167 -41
- package/dist/types/utils/heap.d.ts +21 -0
- package/package.json +2 -2
package/dist/cjs/index.js
CHANGED
|
@@ -8339,7 +8339,7 @@ var require_cjs = __commonJS({
|
|
|
8339
8339
|
this.maxBodySize = this.pfs.pageSize - DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
|
|
8340
8340
|
this.order = this.getOptimalOrder(pfs.pageSize, IndexPageManager.CONSTANT.SIZE_KEY, IndexPageManager.CONSTANT.SIZE_VALUE);
|
|
8341
8341
|
this.strategy = new RowIdentifierStrategy(this.order, pfs, txContext);
|
|
8342
|
-
const budget = import_node_os.default.freemem() * 0.
|
|
8342
|
+
const budget = import_node_os.default.freemem() * 0.1;
|
|
8343
8343
|
const nodeMemory = this.order * 24 + 256;
|
|
8344
8344
|
const capacity = Math.max(1e3, Math.min(1e6, Math.floor(budget / nodeMemory)));
|
|
8345
8345
|
this.bptree = new BPTreeAsync2(
|
|
@@ -9616,6 +9616,71 @@ async function catchPromise(promise) {
|
|
|
9616
9616
|
return promise.then((res) => [void 0, res]).catch((reason) => [reason]);
|
|
9617
9617
|
}
|
|
9618
9618
|
|
|
9619
|
+
// src/utils/heap.ts
|
|
9620
|
+
var BinaryHeap = class {
|
|
9621
|
+
constructor(comparator) {
|
|
9622
|
+
this.comparator = comparator;
|
|
9623
|
+
}
|
|
9624
|
+
heap = [];
|
|
9625
|
+
get size() {
|
|
9626
|
+
return this.heap.length;
|
|
9627
|
+
}
|
|
9628
|
+
peek() {
|
|
9629
|
+
return this.heap[0];
|
|
9630
|
+
}
|
|
9631
|
+
push(value) {
|
|
9632
|
+
this.heap.push(value);
|
|
9633
|
+
this.bubbleUp(this.heap.length - 1);
|
|
9634
|
+
}
|
|
9635
|
+
pop() {
|
|
9636
|
+
if (this.size === 0) return void 0;
|
|
9637
|
+
const top = this.heap[0];
|
|
9638
|
+
const bottom = this.heap.pop();
|
|
9639
|
+
if (this.size > 0) {
|
|
9640
|
+
this.heap[0] = bottom;
|
|
9641
|
+
this.sinkDown(0);
|
|
9642
|
+
}
|
|
9643
|
+
return top;
|
|
9644
|
+
}
|
|
9645
|
+
/**
|
|
9646
|
+
* Replace the root element with a new value and re-heapify.
|
|
9647
|
+
* Faster than pop() followed by push().
|
|
9648
|
+
*/
|
|
9649
|
+
replace(value) {
|
|
9650
|
+
const top = this.heap[0];
|
|
9651
|
+
this.heap[0] = value;
|
|
9652
|
+
this.sinkDown(0);
|
|
9653
|
+
return top;
|
|
9654
|
+
}
|
|
9655
|
+
toArray() {
|
|
9656
|
+
return [...this.heap];
|
|
9657
|
+
}
|
|
9658
|
+
bubbleUp(index) {
|
|
9659
|
+
while (index > 0) {
|
|
9660
|
+
const parentIndex = Math.floor((index - 1) / 2);
|
|
9661
|
+
if (this.comparator(this.heap[index], this.heap[parentIndex]) >= 0) break;
|
|
9662
|
+
[this.heap[index], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[index]];
|
|
9663
|
+
index = parentIndex;
|
|
9664
|
+
}
|
|
9665
|
+
}
|
|
9666
|
+
sinkDown(index) {
|
|
9667
|
+
while (true) {
|
|
9668
|
+
let smallest = index;
|
|
9669
|
+
const left = 2 * index + 1;
|
|
9670
|
+
const right = 2 * index + 2;
|
|
9671
|
+
if (left < this.size && this.comparator(this.heap[left], this.heap[smallest]) < 0) {
|
|
9672
|
+
smallest = left;
|
|
9673
|
+
}
|
|
9674
|
+
if (right < this.size && this.comparator(this.heap[right], this.heap[smallest]) < 0) {
|
|
9675
|
+
smallest = right;
|
|
9676
|
+
}
|
|
9677
|
+
if (smallest === index) break;
|
|
9678
|
+
[this.heap[index], this.heap[smallest]] = [this.heap[smallest], this.heap[index]];
|
|
9679
|
+
index = smallest;
|
|
9680
|
+
}
|
|
9681
|
+
}
|
|
9682
|
+
};
|
|
9683
|
+
|
|
9619
9684
|
// src/core/document.ts
|
|
9620
9685
|
var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
9621
9686
|
indices = {};
|
|
@@ -10242,6 +10307,7 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
10242
10307
|
const keySet = await self.getKeys(query, orderByField, sortOrder);
|
|
10243
10308
|
const keys = new Uint32Array(keySet);
|
|
10244
10309
|
const totalKeys = keys.length;
|
|
10310
|
+
if (totalKeys === 0) return;
|
|
10245
10311
|
const selectivity = await self.getSelectivityCandidate(
|
|
10246
10312
|
self.verboseQuery(query),
|
|
10247
10313
|
orderByField
|
|
@@ -10252,29 +10318,70 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
10252
10318
|
}
|
|
10253
10319
|
let CHUNK_SIZE = 100;
|
|
10254
10320
|
if (!isDriverOrderByField && orderByField) {
|
|
10321
|
+
const isTopK = limit !== Infinity;
|
|
10322
|
+
const heapSizeLimit = isTopK ? limit + offset : Infinity;
|
|
10323
|
+
const heapComparator = (a, b) => {
|
|
10324
|
+
const aVal = a[orderByField] ?? a._id;
|
|
10325
|
+
const bVal = b[orderByField] ?? b._id;
|
|
10326
|
+
const cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
10327
|
+
return sortOrder === "asc" ? -cmp : cmp;
|
|
10328
|
+
};
|
|
10329
|
+
const heap = isTopK ? new BinaryHeap(heapComparator) : null;
|
|
10255
10330
|
const results = [];
|
|
10256
10331
|
let i = 0;
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10332
|
+
const firstChunk = Array.from(keys.subarray(i, i + 100));
|
|
10333
|
+
const firstResults = await self.api.selectMany(firstChunk, false, tx2);
|
|
10334
|
+
let totalBytes = 0;
|
|
10335
|
+
let count = 0;
|
|
10336
|
+
for (const s of firstResults) {
|
|
10337
|
+
if (!s) continue;
|
|
10338
|
+
totalBytes += s.length;
|
|
10339
|
+
count++;
|
|
10340
|
+
const doc = JSON.parse(s);
|
|
10341
|
+
if (heap) {
|
|
10342
|
+
if (heap.size < heapSizeLimit) {
|
|
10343
|
+
heap.push(doc);
|
|
10344
|
+
} else if (heapComparator(doc, heap.peek()) > 0) {
|
|
10345
|
+
heap.replace(doc);
|
|
10268
10346
|
}
|
|
10269
|
-
|
|
10270
|
-
|
|
10347
|
+
} else {
|
|
10348
|
+
results.push(doc);
|
|
10349
|
+
}
|
|
10350
|
+
}
|
|
10351
|
+
const avgSize = count > 0 ? totalBytes / count : 1024;
|
|
10352
|
+
CHUNK_SIZE = Math.max(32, Math.floor(os.freemem() * 0.1 / avgSize));
|
|
10353
|
+
i += firstChunk.length;
|
|
10354
|
+
let nextSortChunkPromise = null;
|
|
10355
|
+
if (i < totalKeys) {
|
|
10356
|
+
const nextChunk = Array.from(keys.subarray(i, i + CHUNK_SIZE));
|
|
10357
|
+
nextSortChunkPromise = self.api.selectMany(nextChunk, false, tx2);
|
|
10358
|
+
i += nextChunk.length;
|
|
10359
|
+
}
|
|
10360
|
+
while (nextSortChunkPromise) {
|
|
10361
|
+
const stringifiedResults = await nextSortChunkPromise;
|
|
10362
|
+
if (i < totalKeys) {
|
|
10363
|
+
const nextChunk = Array.from(keys.subarray(i, i + CHUNK_SIZE));
|
|
10364
|
+
nextSortChunkPromise = self.api.selectMany(nextChunk, false, tx2);
|
|
10365
|
+
i += nextChunk.length;
|
|
10366
|
+
} else {
|
|
10367
|
+
nextSortChunkPromise = null;
|
|
10271
10368
|
}
|
|
10272
10369
|
for (const stringified of stringifiedResults) {
|
|
10273
|
-
if (stringified)
|
|
10370
|
+
if (!stringified) continue;
|
|
10371
|
+
const doc = JSON.parse(stringified);
|
|
10372
|
+
if (heap) {
|
|
10373
|
+
if (heap.size < heapSizeLimit) {
|
|
10374
|
+
heap.push(doc);
|
|
10375
|
+
} else if (heapComparator(doc, heap.peek()) > 0) {
|
|
10376
|
+
heap.replace(doc);
|
|
10377
|
+
}
|
|
10378
|
+
} else {
|
|
10379
|
+
results.push(doc);
|
|
10380
|
+
}
|
|
10274
10381
|
}
|
|
10275
|
-
i += chunk.length;
|
|
10276
10382
|
}
|
|
10277
|
-
|
|
10383
|
+
const finalResults = heap ? heap.toArray() : results;
|
|
10384
|
+
finalResults.sort((a, b) => {
|
|
10278
10385
|
const aVal = a[orderByField] ?? a._id;
|
|
10279
10386
|
const bVal = b[orderByField] ?? b._id;
|
|
10280
10387
|
const cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
@@ -10282,41 +10389,60 @@ var DocumentDataply = class _DocumentDataply {
|
|
|
10282
10389
|
});
|
|
10283
10390
|
const start = offset;
|
|
10284
10391
|
const end = limit === Infinity ? void 0 : start + limit;
|
|
10285
|
-
const limitedResults =
|
|
10392
|
+
const limitedResults = finalResults.slice(start, end);
|
|
10286
10393
|
for (const doc of limitedResults) {
|
|
10287
10394
|
yield doc;
|
|
10288
10395
|
}
|
|
10289
10396
|
} else {
|
|
10290
10397
|
let yieldedCount = 0;
|
|
10291
10398
|
let i = offset;
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
if (
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10399
|
+
if (i >= totalKeys || yieldedCount >= limit) return;
|
|
10400
|
+
const pksToFetchCount = Math.min(100, limit - yieldedCount);
|
|
10401
|
+
const firstChunk = Array.from(keys.subarray(i, i + pksToFetchCount));
|
|
10402
|
+
const firstResults = await self.api.selectMany(firstChunk, false, tx2);
|
|
10403
|
+
let totalBytes = 0;
|
|
10404
|
+
let count = 0;
|
|
10405
|
+
for (const s of firstResults) {
|
|
10406
|
+
if (!s) continue;
|
|
10407
|
+
yield JSON.parse(s);
|
|
10408
|
+
yieldedCount++;
|
|
10409
|
+
totalBytes += s.length;
|
|
10410
|
+
count++;
|
|
10411
|
+
if (yieldedCount >= limit) break;
|
|
10412
|
+
}
|
|
10413
|
+
const avgSize = count > 0 ? totalBytes / count : 1024;
|
|
10414
|
+
CHUNK_SIZE = Math.max(32, Math.floor(os.freemem() * 0.1 / avgSize));
|
|
10415
|
+
i += firstChunk.length;
|
|
10416
|
+
let nextStreamChunkPromise = null;
|
|
10417
|
+
if (i < totalKeys && yieldedCount < limit) {
|
|
10418
|
+
const nextPksToFetchCount = Math.min(CHUNK_SIZE, limit - yieldedCount);
|
|
10419
|
+
const nextChunk = Array.from(keys.subarray(i, i + nextPksToFetchCount));
|
|
10420
|
+
nextStreamChunkPromise = self.api.selectMany(nextChunk, false, tx2);
|
|
10421
|
+
i += nextChunk.length;
|
|
10422
|
+
}
|
|
10423
|
+
while (nextStreamChunkPromise) {
|
|
10424
|
+
const stringifiedResults = await nextStreamChunkPromise;
|
|
10425
|
+
if (i < totalKeys && yieldedCount < limit) {
|
|
10426
|
+
const nextPksToFetchCount = Math.min(CHUNK_SIZE, limit - (yieldedCount + stringifiedResults.filter(Boolean).length));
|
|
10427
|
+
if (nextPksToFetchCount > 0) {
|
|
10428
|
+
const nextChunk = Array.from(keys.subarray(i, i + nextPksToFetchCount));
|
|
10429
|
+
nextStreamChunkPromise = self.api.selectMany(nextChunk, false, tx2);
|
|
10430
|
+
i += nextChunk.length;
|
|
10431
|
+
} else {
|
|
10432
|
+
nextStreamChunkPromise = null;
|
|
10307
10433
|
}
|
|
10308
|
-
|
|
10309
|
-
|
|
10310
|
-
isFirst = false;
|
|
10434
|
+
} else {
|
|
10435
|
+
nextStreamChunkPromise = null;
|
|
10311
10436
|
}
|
|
10312
10437
|
for (const stringified of stringifiedResults) {
|
|
10313
|
-
if (stringified)
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10438
|
+
if (!stringified) continue;
|
|
10439
|
+
yield JSON.parse(stringified);
|
|
10440
|
+
yieldedCount++;
|
|
10441
|
+
if (yieldedCount >= limit) {
|
|
10442
|
+
nextStreamChunkPromise = null;
|
|
10443
|
+
break;
|
|
10317
10444
|
}
|
|
10318
10445
|
}
|
|
10319
|
-
i += chunk.length;
|
|
10320
10446
|
}
|
|
10321
10447
|
}
|
|
10322
10448
|
}, tx);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type Comparator<T> = (a: T, b: T) => number;
|
|
2
|
+
/**
|
|
3
|
+
* A simple Binary Heap implementation.
|
|
4
|
+
*/
|
|
5
|
+
export declare class BinaryHeap<T> {
|
|
6
|
+
private comparator;
|
|
7
|
+
private heap;
|
|
8
|
+
constructor(comparator: Comparator<T>);
|
|
9
|
+
get size(): number;
|
|
10
|
+
peek(): T | undefined;
|
|
11
|
+
push(value: T): void;
|
|
12
|
+
pop(): T | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Replace the root element with a new value and re-heapify.
|
|
15
|
+
* Faster than pop() followed by push().
|
|
16
|
+
*/
|
|
17
|
+
replace(value: T): T | undefined;
|
|
18
|
+
toArray(): T[];
|
|
19
|
+
private bubbleUp;
|
|
20
|
+
private sinkDown;
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-dataply",
|
|
3
|
-
"version": "0.0.4
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Simple and powerful JSON document database supporting complex queries and flexible indexing policies.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "izure <admin@izure.org>",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"dataply"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"dataply": "^0.0.20
|
|
45
|
+
"dataply": "^0.0.20"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/jest": "^30.0.0",
|