document-dataply 0.0.9-alpha.12 → 0.0.9-alpha.14
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 +168 -30
- package/package.json +3 -3
package/dist/cjs/index.js
CHANGED
|
@@ -6485,21 +6485,68 @@ var require_cjs = __commonJS({
|
|
|
6485
6485
|
}
|
|
6486
6486
|
return (crc ^ -1) >>> 0;
|
|
6487
6487
|
}
|
|
6488
|
-
function
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6488
|
+
function calcThreshold(sortedGaps, n) {
|
|
6489
|
+
const gLen = sortedGaps.length;
|
|
6490
|
+
if (gLen === 0) return 0;
|
|
6491
|
+
const median = sortedGaps[Math.floor(gLen * 0.5)];
|
|
6492
|
+
const q1 = sortedGaps[Math.floor(gLen * 0.25)];
|
|
6493
|
+
const q3 = sortedGaps[Math.floor(gLen * 0.75)];
|
|
6494
|
+
const iqr = q3 - q1;
|
|
6495
|
+
const logN = Math.max(1, Math.log10(n));
|
|
6496
|
+
if (iqr > 0) {
|
|
6497
|
+
const threshold2 = q3 + iqr * 1.5 * logN;
|
|
6498
|
+
const minJump = Math.max(median * 5, 20);
|
|
6499
|
+
return Math.max(threshold2, minJump);
|
|
6500
|
+
}
|
|
6501
|
+
const baseGap = median > 0 ? median : 1;
|
|
6502
|
+
const p90 = sortedGaps[Math.floor(gLen * 0.9)];
|
|
6503
|
+
if (p90 > baseGap) {
|
|
6504
|
+
const threshold2 = baseGap + (p90 - baseGap) * 0.5 * logN;
|
|
6505
|
+
return Math.max(threshold2, baseGap * 5, 20);
|
|
6506
|
+
}
|
|
6507
|
+
let mean = 0;
|
|
6508
|
+
for (let i = 0; i < gLen; i++) mean += sortedGaps[i];
|
|
6509
|
+
mean /= gLen;
|
|
6510
|
+
let variance = 0;
|
|
6511
|
+
for (let i = 0; i < gLen; i++) {
|
|
6512
|
+
const d = sortedGaps[i] - mean;
|
|
6513
|
+
variance += d * d;
|
|
6514
|
+
}
|
|
6515
|
+
const stddev = Math.sqrt(variance / gLen);
|
|
6516
|
+
if (stddev === 0) {
|
|
6517
|
+
return baseGap * 2;
|
|
6518
|
+
}
|
|
6519
|
+
const threshold = mean + stddev * logN;
|
|
6520
|
+
return Math.max(threshold, baseGap * 5, 20);
|
|
6521
|
+
}
|
|
6522
|
+
function clusterNumbers(numbers, gapMultiplier) {
|
|
6523
|
+
const n = numbers.length;
|
|
6524
|
+
if (n === 0) return [];
|
|
6525
|
+
if (n === 1) return [new Float64Array([numbers[0]])];
|
|
6526
|
+
const sorted = (numbers instanceof Float64Array ? numbers.slice() : Float64Array.from(numbers)).sort();
|
|
6527
|
+
const gaps = new Float64Array(n - 1);
|
|
6528
|
+
for (let i = 0, len = n - 1; i < len; i++) {
|
|
6529
|
+
gaps[i] = sorted[i + 1] - sorted[i];
|
|
6530
|
+
}
|
|
6531
|
+
const sortedGaps = gaps.slice().sort();
|
|
6532
|
+
let threshold;
|
|
6533
|
+
if (gapMultiplier !== void 0) {
|
|
6534
|
+
const q3 = sortedGaps[Math.floor((n - 1) * 0.75)];
|
|
6535
|
+
const iqr = q3 - sortedGaps[Math.floor((n - 1) * 0.25)];
|
|
6536
|
+
threshold = q3 + iqr * gapMultiplier;
|
|
6537
|
+
} else {
|
|
6538
|
+
threshold = calcThreshold(sortedGaps, n);
|
|
6539
|
+
}
|
|
6540
|
+
const clusters = [];
|
|
6541
|
+
let clusterStart = 0;
|
|
6542
|
+
for (let i = 0, len = n - 1; i < len; i++) {
|
|
6543
|
+
if (gaps[i] > threshold) {
|
|
6544
|
+
clusters.push(sorted.subarray(clusterStart, i + 1));
|
|
6545
|
+
clusterStart = i + 1;
|
|
6499
6546
|
}
|
|
6500
|
-
i++;
|
|
6501
6547
|
}
|
|
6502
|
-
|
|
6548
|
+
clusters.push(sorted.subarray(clusterStart));
|
|
6549
|
+
return clusters;
|
|
6503
6550
|
}
|
|
6504
6551
|
var Row = class _Row {
|
|
6505
6552
|
static CONSTANT = {
|
|
@@ -9439,14 +9486,30 @@ var require_cjs = __commonJS({
|
|
|
9439
9486
|
for (let i = 0, len = pks.length; i < len; i++) {
|
|
9440
9487
|
pkIndexMap.set(pks[i], i);
|
|
9441
9488
|
}
|
|
9442
|
-
const [minPk, maxPk] = getMinMaxValue(pks);
|
|
9443
9489
|
const pkRidPairs = new Array(pks.length).fill(null);
|
|
9444
9490
|
const btx = await this.getBPTreeTransaction(tx);
|
|
9445
|
-
const
|
|
9446
|
-
for
|
|
9447
|
-
const
|
|
9448
|
-
|
|
9449
|
-
|
|
9491
|
+
const clusters = clusterNumbers(pks);
|
|
9492
|
+
for (let i = 0, len = clusters.length; i < len; i++) {
|
|
9493
|
+
const cluster = clusters[i];
|
|
9494
|
+
const minPk = cluster[0];
|
|
9495
|
+
const maxPk = cluster[cluster.length - 1];
|
|
9496
|
+
if (minPk === maxPk) {
|
|
9497
|
+
const keys = await btx.keys({ equal: minPk });
|
|
9498
|
+
if (keys.size > 0) {
|
|
9499
|
+
const rid = keys.values().next().value;
|
|
9500
|
+
const index = pkIndexMap.get(minPk);
|
|
9501
|
+
if (index !== void 0) {
|
|
9502
|
+
pkRidPairs[index] = { pk: minPk, rid, index };
|
|
9503
|
+
}
|
|
9504
|
+
}
|
|
9505
|
+
continue;
|
|
9506
|
+
}
|
|
9507
|
+
const stream = btx.whereStream({ gte: minPk, lte: maxPk });
|
|
9508
|
+
for await (const [rid, pk] of stream) {
|
|
9509
|
+
const index = pkIndexMap.get(pk);
|
|
9510
|
+
if (index !== void 0) {
|
|
9511
|
+
pkRidPairs[index] = { pk, rid, index };
|
|
9512
|
+
}
|
|
9450
9513
|
}
|
|
9451
9514
|
}
|
|
9452
9515
|
return this.fetchRowsByRids(pkRidPairs, tx);
|
|
@@ -10934,7 +10997,8 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
10934
10997
|
const doc = await this.getDocument(k, tx2);
|
|
10935
10998
|
if (!doc) continue;
|
|
10936
10999
|
const flatDoc = this.flattenDocument(doc);
|
|
10937
|
-
for (
|
|
11000
|
+
for (let i = 0, len = backfillTargets.length; i < len; i++) {
|
|
11001
|
+
const indexName = backfillTargets[i];
|
|
10938
11002
|
if (!(indexName in indexTxMap)) continue;
|
|
10939
11003
|
const config = this.registeredIndices.get(indexName);
|
|
10940
11004
|
if (!config) continue;
|
|
@@ -10946,8 +11010,8 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
10946
11010
|
const ftsConfig = this.getFtsConfig(config);
|
|
10947
11011
|
const tokens = ftsConfig ? tokenize(v, ftsConfig) : [v];
|
|
10948
11012
|
const batchInsertData = [];
|
|
10949
|
-
for (let
|
|
10950
|
-
const token = tokens[
|
|
11013
|
+
for (let i2 = 0, len2 = tokens.length; i2 < len2; i2++) {
|
|
11014
|
+
const token = tokens[i2];
|
|
10951
11015
|
const keyToInsert = this.getTokenKey(k, token);
|
|
10952
11016
|
const entry = { k, v: token };
|
|
10953
11017
|
batchInsertData.push([keyToInsert, entry]);
|
|
@@ -11148,13 +11212,18 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
11148
11212
|
if (config.type === "btree") {
|
|
11149
11213
|
const primaryField = config.fields[0];
|
|
11150
11214
|
if (!queryFields.has(primaryField)) continue;
|
|
11151
|
-
const condition = query[primaryField];
|
|
11152
11215
|
const treeTx = await tree.createTransaction();
|
|
11216
|
+
const builtCondition = {};
|
|
11153
11217
|
let score = 0;
|
|
11154
11218
|
let isConsecutive = true;
|
|
11155
11219
|
const coveredFields = [];
|
|
11156
11220
|
const compositeVerifyFields = [];
|
|
11157
|
-
|
|
11221
|
+
const startValues = [];
|
|
11222
|
+
const endValues = [];
|
|
11223
|
+
let startOperator = null;
|
|
11224
|
+
let endOperator = null;
|
|
11225
|
+
for (let i = 0, len = config.fields.length; i < len; i++) {
|
|
11226
|
+
const field = config.fields[i];
|
|
11158
11227
|
if (!queryFields.has(field)) {
|
|
11159
11228
|
isConsecutive = false;
|
|
11160
11229
|
continue;
|
|
@@ -11169,11 +11238,53 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
11169
11238
|
if (cond !== void 0) {
|
|
11170
11239
|
if (typeof cond !== "object" || cond === null) {
|
|
11171
11240
|
score += 100;
|
|
11241
|
+
startValues.push(cond);
|
|
11242
|
+
endValues.push(cond);
|
|
11243
|
+
startOperator = "primaryGte";
|
|
11244
|
+
endOperator = "primaryLte";
|
|
11172
11245
|
} else if ("primaryEqual" in cond || "equal" in cond) {
|
|
11246
|
+
const val = cond.primaryEqual?.v ?? cond.equal?.v ?? cond.primaryEqual ?? cond.equal;
|
|
11173
11247
|
score += 100;
|
|
11174
|
-
|
|
11248
|
+
startValues.push(val);
|
|
11249
|
+
endValues.push(val);
|
|
11250
|
+
startOperator = "primaryGte";
|
|
11251
|
+
endOperator = "primaryLte";
|
|
11252
|
+
} else if ("primaryGte" in cond || "gte" in cond) {
|
|
11253
|
+
const val = cond.primaryGte?.v ?? cond.gte?.v ?? cond.primaryGte ?? cond.gte;
|
|
11254
|
+
score += 50;
|
|
11255
|
+
isConsecutive = false;
|
|
11256
|
+
startValues.push(val);
|
|
11257
|
+
startOperator = "primaryGte";
|
|
11258
|
+
if (endValues.length > 0) {
|
|
11259
|
+
endOperator = "primaryLte";
|
|
11260
|
+
}
|
|
11261
|
+
} else if ("primaryGt" in cond || "gt" in cond) {
|
|
11262
|
+
const val = cond.primaryGt?.v ?? cond.gt?.v ?? cond.primaryGt ?? cond.gt;
|
|
11263
|
+
score += 50;
|
|
11264
|
+
isConsecutive = false;
|
|
11265
|
+
startValues.push(val);
|
|
11266
|
+
startOperator = "primaryGt";
|
|
11267
|
+
if (endValues.length > 0) {
|
|
11268
|
+
endOperator = "primaryLte";
|
|
11269
|
+
}
|
|
11270
|
+
} else if ("primaryLte" in cond || "lte" in cond) {
|
|
11271
|
+
const val = cond.primaryLte?.v ?? cond.lte?.v ?? cond.primaryLte ?? cond.lte;
|
|
11272
|
+
score += 50;
|
|
11273
|
+
isConsecutive = false;
|
|
11274
|
+
endValues.push(val);
|
|
11275
|
+
endOperator = "primaryLte";
|
|
11276
|
+
if (startValues.length > 0) {
|
|
11277
|
+
startOperator = "primaryGte";
|
|
11278
|
+
}
|
|
11279
|
+
} else if ("primaryLt" in cond || "lt" in cond) {
|
|
11280
|
+
const val = cond.primaryLt?.v ?? cond.lt?.v ?? cond.primaryLt ?? cond.lt;
|
|
11175
11281
|
score += 50;
|
|
11176
11282
|
isConsecutive = false;
|
|
11283
|
+
endValues.push(val);
|
|
11284
|
+
endOperator = "primaryLt";
|
|
11285
|
+
if (startValues.length > 0) {
|
|
11286
|
+
startOperator = "primaryGte";
|
|
11287
|
+
}
|
|
11177
11288
|
} else if ("primaryOr" in cond || "or" in cond) {
|
|
11178
11289
|
score += 20;
|
|
11179
11290
|
isConsecutive = false;
|
|
@@ -11187,9 +11298,28 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
11187
11298
|
}
|
|
11188
11299
|
}
|
|
11189
11300
|
}
|
|
11301
|
+
if (coveredFields.length === 1 && config.fields.length === 1) {
|
|
11302
|
+
Object.assign(builtCondition, query[primaryField]);
|
|
11303
|
+
} else {
|
|
11304
|
+
if (startOperator && startValues.length > 0) {
|
|
11305
|
+
builtCondition[startOperator] = { v: startValues.length === 1 ? startValues[0] : startValues };
|
|
11306
|
+
}
|
|
11307
|
+
if (endOperator && endValues.length > 0) {
|
|
11308
|
+
if (startOperator && startValues.length === endValues.length && startValues.every((val, i) => val === endValues[i])) {
|
|
11309
|
+
delete builtCondition[startOperator];
|
|
11310
|
+
builtCondition["primaryEqual"] = { v: startValues.length === 1 ? startValues[0] : startValues };
|
|
11311
|
+
} else {
|
|
11312
|
+
builtCondition[endOperator] = { v: endValues.length === 1 ? endValues[0] : endValues };
|
|
11313
|
+
}
|
|
11314
|
+
}
|
|
11315
|
+
if (Object.keys(builtCondition).length === 0) {
|
|
11316
|
+
Object.assign(builtCondition, query[primaryField] || {});
|
|
11317
|
+
}
|
|
11318
|
+
}
|
|
11190
11319
|
let isIndexOrderSupported = false;
|
|
11191
11320
|
if (orderByField) {
|
|
11192
|
-
for (
|
|
11321
|
+
for (let i = 0, len = config.fields.length; i < len; i++) {
|
|
11322
|
+
const field = config.fields[i];
|
|
11193
11323
|
if (field === orderByField) {
|
|
11194
11324
|
isIndexOrderSupported = true;
|
|
11195
11325
|
break;
|
|
@@ -11208,7 +11338,7 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
11208
11338
|
}
|
|
11209
11339
|
candidates.push({
|
|
11210
11340
|
tree: treeTx,
|
|
11211
|
-
condition,
|
|
11341
|
+
condition: builtCondition,
|
|
11212
11342
|
field: primaryField,
|
|
11213
11343
|
indexName,
|
|
11214
11344
|
isFtsMatch: false,
|
|
@@ -11246,11 +11376,19 @@ var DocumentDataplyAPI = class extends import_dataply3.DataplyAPI {
|
|
|
11246
11376
|
rollback();
|
|
11247
11377
|
return null;
|
|
11248
11378
|
}
|
|
11249
|
-
candidates.sort((a, b) =>
|
|
11379
|
+
candidates.sort((a, b) => {
|
|
11380
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
11381
|
+
const aConfig = this.registeredIndices.get(a.indexName);
|
|
11382
|
+
const bConfig = this.registeredIndices.get(b.indexName);
|
|
11383
|
+
const aFieldCount = aConfig ? Array.isArray(aConfig.fields) ? aConfig.fields.length : 1 : 0;
|
|
11384
|
+
const bFieldCount = bConfig ? Array.isArray(bConfig.fields) ? bConfig.fields.length : 1 : 0;
|
|
11385
|
+
return aFieldCount - bFieldCount;
|
|
11386
|
+
});
|
|
11250
11387
|
const driver = candidates[0];
|
|
11251
|
-
const others = candidates.slice(1);
|
|
11388
|
+
const others = candidates.slice(1).filter((c) => c.field !== driver.field);
|
|
11252
11389
|
const compositeVerifyConditions = [];
|
|
11253
|
-
for (
|
|
11390
|
+
for (let i = 0, len = driver.compositeVerifyFields.length; i < len; i++) {
|
|
11391
|
+
const field = driver.compositeVerifyFields[i];
|
|
11254
11392
|
if (query[field]) {
|
|
11255
11393
|
compositeVerifyConditions.push({ field, condition: query[field] });
|
|
11256
11394
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "document-dataply",
|
|
3
|
-
"version": "0.0.9-alpha.
|
|
3
|
+
"version": "0.0.9-alpha.14",
|
|
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.24-alpha.
|
|
45
|
+
"dataply": "^0.0.24-alpha.12"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/jest": "^30.0.0",
|
|
@@ -51,4 +51,4 @@
|
|
|
51
51
|
"ts-jest": "^29.4.6",
|
|
52
52
|
"typescript": "^5.9.3"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|