@delali/narsil 0.2.4-next.55 → 0.3.0
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/README.md +39 -28
- package/dist/adapters/filesystem.mjs +1 -1
- package/dist/adapters/indexeddb.mjs +1 -1
- package/dist/{capabilities-DlYw0Ov0.d.ts → capabilities-DSsOGz6F.d.ts} +2 -2
- package/dist/{chunk-BH5SYB5W.mjs → chunk-24RXHMEL.mjs} +604 -150
- package/dist/{chunk-D2S642IV.mjs → chunk-3LHGNRYE.mjs} +1 -1
- package/dist/{chunk-TVT5V4E7.mjs → chunk-B2TFROFX.mjs} +299 -168
- package/dist/{chunk-L225SHNB.mjs → chunk-L6TNPLAR.mjs} +19 -5
- package/dist/{chunk-U2AL3SON.mjs → chunk-THYRHHO2.mjs} +3 -3
- package/dist/{chunk-NTZYA3SJ.mjs → chunk-U7KYW4BA.mjs} +3 -3
- package/dist/{chunk-FRQVMFY7.mjs → chunk-USKFU7J5.mjs} +1 -0
- package/dist/{chunk-4NVPQ6S5.mjs → chunk-UXNWQZST.mjs} +12 -3
- package/dist/{chunk-RGS7FMCB.mjs → chunk-VMRR3DQU.mjs} +74 -16
- package/dist/{chunk-2GWVQWGA.mjs → chunk-YMZCMH5M.mjs} +45 -1
- package/dist/{chunk-UTOFOJOR.mjs → chunk-YNVIUGF5.mjs} +6 -2
- package/dist/{chunk-5T6AOR37.mjs → chunk-ZNZBXMP5.mjs} +601 -60
- package/dist/{chunk-XNQAIO74.mjs → chunk-ZZT3EAUC.mjs} +177 -309
- package/dist/{client-CQUqt9Ir.d.ts → client-BQK6Tf6A.d.ts} +3 -3
- package/dist/client.d.ts +8 -8
- package/dist/client.mjs +1 -0
- package/dist/{config-CNas6wJH.d.ts → config-BhldZgaK.d.ts} +2 -2
- package/dist/{config-bXxnJrQc.d.ts → config-DmXULPa-.d.ts} +15 -7
- package/dist/direct-executor-ALAVE7FC.mjs +12 -0
- package/dist/distribution/coordinator/etcd.d.ts +2 -2
- package/dist/distribution/coordinator/etcd.mjs +2 -2
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution/coordinator/in-memory.mjs +1 -1
- package/dist/distribution/transport/grpc.mjs +1 -1
- package/dist/distribution.d.ts +8 -8
- package/dist/distribution.mjs +382 -162
- package/dist/embeddings/openai.mjs +2 -2
- package/dist/{engine-Dj4I91Jv.d.ts → engine-CIOyFozK.d.ts} +15 -12
- package/dist/index.browser.mjs +1565 -528
- package/dist/index.d.ts +7 -7
- package/dist/index.mjs +11 -11
- package/dist/invalidation/filesystem.mjs +1 -1
- package/dist/{memory-xrXOZMbw.d.ts → memory-yFaVn2xZ.d.ts} +199 -107
- package/dist/persistence/durability/checkpoint-worker.d.ts +1 -1
- package/dist/persistence/durability/checkpoint-worker.mjs +11 -11
- package/dist/react.d.ts +6 -6
- package/dist/react.mjs +1 -0
- package/dist/{schema-mLpXZBEh.d.ts → schema-d5Afu03A.d.ts} +7 -2
- package/dist/server.d.ts +10 -10
- package/dist/server.mjs +10 -10
- package/dist/{tasks-Df73Tjgq.d.ts → tasks-CH2Dod8w.d.ts} +1 -1
- package/dist/{thread-5UP6MGED.mjs → thread-DYHEQRVY.mjs} +14 -10
- package/dist/{types-BTIVO8DI.d.ts → types-DAK7mnUZ.d.ts} +1 -1
- package/dist/vector/search-worker.d.ts +1 -1
- package/dist/vector/search-worker.mjs +4 -4
- package/dist/workers/entry.mjs +4 -4
- package/package.json +9 -9
- package/dist/direct-executor-RBA5O7EN.mjs +0 -12
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { detectRuntime } from './chunk-AV4IJKD2.mjs';
|
|
2
|
-
import { cloneProjected, mergeFacets, visitTokens, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, projectionKeepsField, setNestedValue, fnv1a, bitsetHas, createBitSet, kWayMerge, boundedLevenshtein, bitsetSet, tokenize, bitsetFromSet, tokenizeIterator, bitsetAnd, bitsetOr, bitsetNot } from './chunk-
|
|
3
|
-
import { flattenSchema, validateDocument, validateDocumentStrict, isQuantizationMode, isStorageMode, extractVectorFieldsFromSchema, isTextFieldType, VECTOR_PATTERN } from './chunk-
|
|
2
|
+
import { cloneProjected, everyValueFacetConfig, mergeFacets, computeFacets, tokenizeOptions, getNestedValue, visitTokens, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, getFlatSchema, textFieldsChanged, projectionKeepsField, setNestedValue, fnv1a, bitsetHas, createBitSet, kWayMerge, boundedLevenshtein, bitsetSet, tokenize, bitsetFromSet, getAllInternalDocIds, getFieldValueByInternalId, getOrCreateFieldNameIndex, tokenizeIterator, polygonContainment, requireValidOperands, bitsetAnd, bitsetOr, bitsetNot, requirePolygonRing, VINCENTY_CONVERGENCE_THRESHOLD, VINCENTY_MAX_ITERATIONS, DEG_TO_RAD } from './chunk-ZNZBXMP5.mjs';
|
|
3
|
+
import { flattenSchema, validateDocument, validateDocumentStrict, isQuantizationMode, isStorageMode, extractVectorFieldsFromSchema, isTextFieldType, VECTOR_PATTERN } from './chunk-L6TNPLAR.mjs';
|
|
4
4
|
import { english } from './chunk-TGP5M5R7.mjs';
|
|
5
|
-
import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, addToOrdinalFilter, ordinalFilterValues,
|
|
6
|
-
import { noteFallback } from './chunk-
|
|
5
|
+
import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, isTombstoned, addToOrdinalFilter, ordinalFilterValues, nativeScoresOf, toScore, removeFromOrdinalFilter, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, requireWholeNeighbourLists, STORE_CALIBRATION_GENERATION, entryForOrd, toDistance, sharedMemoryAvailable, GRAPH_BUILD_CHUNKS_IN_FLIGHT_PER_WORKER, GRAPH_BUILD_DISPATCH_CHUNK, releaseLocksHeldBy, VECTOR_SEARCH_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, VECTOR_INSERT_TIMEOUT_MS, VECTOR_SCRATCH_SLOTS } from './chunk-THYRHHO2.mjs';
|
|
6
|
+
import { noteFallback } from './chunk-YNVIUGF5.mjs';
|
|
7
7
|
import { VALID_HNSW_METRICS } from './chunk-IFBKLBGB.mjs';
|
|
8
|
-
import { compareCodePoints,
|
|
9
|
-
import { NarsilError, ErrorCodes } from './chunk-
|
|
8
|
+
import { compareCodePoints, toReducedSortValue, readSortField, compareComparableValues, defaultSortMode, SORT_VALUE_MAX_CODE_POINTS } from './chunk-YMZCMH5M.mjs';
|
|
9
|
+
import { NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
|
|
10
10
|
import { totalmem } from 'os';
|
|
11
11
|
import { getHeapStatistics } from 'v8';
|
|
12
12
|
import { encode, decode } from '@msgpack/msgpack';
|
|
@@ -1415,215 +1415,6 @@ function createSurfaceRegistry() {
|
|
|
1415
1415
|
};
|
|
1416
1416
|
}
|
|
1417
1417
|
|
|
1418
|
-
// src/core/partition/utils.ts
|
|
1419
|
-
function getOrCreateFieldNameIndex(table, fieldName) {
|
|
1420
|
-
const existing = table.indexMap.get(fieldName);
|
|
1421
|
-
if (existing !== void 0) return existing;
|
|
1422
|
-
const idx = table.names.length;
|
|
1423
|
-
table.names.push(fieldName);
|
|
1424
|
-
table.indexMap.set(fieldName, idx);
|
|
1425
|
-
return idx;
|
|
1426
|
-
}
|
|
1427
|
-
function getNestedValue(obj, path) {
|
|
1428
|
-
const parts = path.split(".");
|
|
1429
|
-
let current = obj;
|
|
1430
|
-
for (let i = 0; i < parts.length; i++) {
|
|
1431
|
-
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
1432
|
-
current = current[parts[i]];
|
|
1433
|
-
}
|
|
1434
|
-
return current;
|
|
1435
|
-
}
|
|
1436
|
-
function stringArraysEqual(a, b) {
|
|
1437
|
-
if (a === b) return true;
|
|
1438
|
-
if (!a || !b) return false;
|
|
1439
|
-
if (a.length !== b.length) return false;
|
|
1440
|
-
for (let i = 0; i < a.length; i++) {
|
|
1441
|
-
if (a[i] !== b[i]) return false;
|
|
1442
|
-
}
|
|
1443
|
-
return true;
|
|
1444
|
-
}
|
|
1445
|
-
function textFieldsChanged(oldDoc, newDoc, flatSchema) {
|
|
1446
|
-
for (const [path, fieldType] of Object.entries(flatSchema)) {
|
|
1447
|
-
if (!isTextFieldType(fieldType) && fieldType !== "string[]") continue;
|
|
1448
|
-
const oldVal = getNestedValue(oldDoc, path);
|
|
1449
|
-
const newVal = getNestedValue(newDoc, path);
|
|
1450
|
-
if (fieldType !== "string[]") {
|
|
1451
|
-
if (oldVal !== newVal) return true;
|
|
1452
|
-
} else {
|
|
1453
|
-
if (!stringArraysEqual(oldVal, newVal)) return true;
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
return false;
|
|
1457
|
-
}
|
|
1458
|
-
function tokenizeOptions(options) {
|
|
1459
|
-
return {
|
|
1460
|
-
stem: true,
|
|
1461
|
-
removeStopWords: true,
|
|
1462
|
-
collectSurfaces: options?.collectSurfaces === true,
|
|
1463
|
-
stopWordOverride: options?.stopWordOverride,
|
|
1464
|
-
customTokenizer: options?.customTokenizer
|
|
1465
|
-
};
|
|
1466
|
-
}
|
|
1467
|
-
function getFlatSchema(state, schema) {
|
|
1468
|
-
if (state.lastSchemaRef === schema && state.flatSchemaCache) return state.flatSchemaCache;
|
|
1469
|
-
state.flatSchemaCache = flattenSchema(schema);
|
|
1470
|
-
state.lastSchemaRef = schema;
|
|
1471
|
-
return state.flatSchemaCache;
|
|
1472
|
-
}
|
|
1473
|
-
function getFieldValueForDoc(docStore, docId, fieldPath) {
|
|
1474
|
-
const stored = docStore.get(docId);
|
|
1475
|
-
if (!stored) return void 0;
|
|
1476
|
-
return getNestedValue(stored.fields, fieldPath);
|
|
1477
|
-
}
|
|
1478
|
-
function getFieldValueByInternalId(docStore, internalId, fieldPath) {
|
|
1479
|
-
const externalId = docStore.getExternalId(internalId);
|
|
1480
|
-
if (externalId === void 0) return void 0;
|
|
1481
|
-
return getFieldValueForDoc(docStore, externalId, fieldPath);
|
|
1482
|
-
}
|
|
1483
|
-
function getAllInternalDocIds(docStore) {
|
|
1484
|
-
const ids = /* @__PURE__ */ new Set();
|
|
1485
|
-
for (const internalId of docStore.allInternalIds()) {
|
|
1486
|
-
ids.add(internalId);
|
|
1487
|
-
}
|
|
1488
|
-
return ids;
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
// src/core/partition/facets.ts
|
|
1492
|
-
function ordinalBitsetOf(state, matched) {
|
|
1493
|
-
if ("ordinalBitset" in matched) return matched.ordinalBitset;
|
|
1494
|
-
const bitset = createBitSet(state.docStore.internalIdCapacity());
|
|
1495
|
-
for (const docId of matched) {
|
|
1496
|
-
const ordinal = state.docStore.getInternalId(docId);
|
|
1497
|
-
if (ordinal !== void 0) bitsetSet(bitset, ordinal);
|
|
1498
|
-
}
|
|
1499
|
-
return bitset;
|
|
1500
|
-
}
|
|
1501
|
-
function* matchedFieldValues(state, fieldPath, matched) {
|
|
1502
|
-
if ("ordinalBitset" in matched) {
|
|
1503
|
-
const bits = matched.ordinalBitset;
|
|
1504
|
-
for (let wordIndex = 0; wordIndex < bits.length; wordIndex++) {
|
|
1505
|
-
let word = bits[wordIndex];
|
|
1506
|
-
if (word === 0) continue;
|
|
1507
|
-
const base = wordIndex << 5;
|
|
1508
|
-
while (word !== 0) {
|
|
1509
|
-
const trailingZeros = Math.clz32(word & -word) ^ 31;
|
|
1510
|
-
yield getFieldValueByInternalId(state.docStore, base + trailingZeros, fieldPath);
|
|
1511
|
-
word &= word - 1;
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
return;
|
|
1515
|
-
}
|
|
1516
|
-
for (const docId of matched) {
|
|
1517
|
-
yield getFieldValueForDoc(state.docStore, docId, fieldPath);
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
function countValuesFromDocuments(state, fieldPath, matched) {
|
|
1521
|
-
const counts = /* @__PURE__ */ new Map();
|
|
1522
|
-
for (const value of matchedFieldValues(state, fieldPath, matched)) {
|
|
1523
|
-
if (value === void 0 || value === null) continue;
|
|
1524
|
-
if (Array.isArray(value)) {
|
|
1525
|
-
for (const item of value) {
|
|
1526
|
-
const key = String(item);
|
|
1527
|
-
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1528
|
-
}
|
|
1529
|
-
} else {
|
|
1530
|
-
const key = String(value);
|
|
1531
|
-
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
return counts;
|
|
1535
|
-
}
|
|
1536
|
-
function countRangeFromDocuments(state, fieldPath, fieldType, range, matched) {
|
|
1537
|
-
let count = 0;
|
|
1538
|
-
for (const value of matchedFieldValues(state, fieldPath, matched)) {
|
|
1539
|
-
if (fieldType === "number[]" && Array.isArray(value)) {
|
|
1540
|
-
for (const v of value) {
|
|
1541
|
-
if (v >= range.from && v < range.to) {
|
|
1542
|
-
count++;
|
|
1543
|
-
break;
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
} else if (typeof value === "number" && value >= range.from && value < range.to) {
|
|
1547
|
-
count++;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
return count;
|
|
1551
|
-
}
|
|
1552
|
-
function countNumericRanges(state, fieldPath, fieldType, ranges, bitset, matched) {
|
|
1553
|
-
const counts = /* @__PURE__ */ new Map();
|
|
1554
|
-
const index = state.numericIndexes.get(fieldPath);
|
|
1555
|
-
for (const range of ranges) {
|
|
1556
|
-
const label = `${range.from}-${range.to}`;
|
|
1557
|
-
if (index === void 0) {
|
|
1558
|
-
counts.set(label, countRangeFromDocuments(state, fieldPath, fieldType, range, matched));
|
|
1559
|
-
} else if (Number.isNaN(range.from) || Number.isNaN(range.to)) {
|
|
1560
|
-
counts.set(label, 0);
|
|
1561
|
-
} else {
|
|
1562
|
-
counts.set(label, index.facetRangeCount(range.from, range.to, bitset()));
|
|
1563
|
-
}
|
|
1564
|
-
}
|
|
1565
|
-
return counts;
|
|
1566
|
-
}
|
|
1567
|
-
function countFieldValues(state, fieldPath, fieldType, bitset, matched) {
|
|
1568
|
-
if (fieldType === "enum" || fieldType === "enum[]") {
|
|
1569
|
-
const index = state.enumIndexes.get(fieldPath);
|
|
1570
|
-
if (index !== void 0) return index.facetCounts(bitset());
|
|
1571
|
-
} else if (fieldType === "boolean" || fieldType === "boolean[]") {
|
|
1572
|
-
const index = state.booleanIndexes.get(fieldPath);
|
|
1573
|
-
if (index !== void 0) {
|
|
1574
|
-
const { trueCount, falseCount } = index.facetCounts(bitset());
|
|
1575
|
-
const counts = /* @__PURE__ */ new Map();
|
|
1576
|
-
if (trueCount > 0) counts.set("true", trueCount);
|
|
1577
|
-
if (falseCount > 0) counts.set("false", falseCount);
|
|
1578
|
-
return counts;
|
|
1579
|
-
}
|
|
1580
|
-
} else if (fieldType === "number" || fieldType === "number[]") {
|
|
1581
|
-
const index = state.numericIndexes.get(fieldPath);
|
|
1582
|
-
if (index !== void 0) {
|
|
1583
|
-
const counts = /* @__PURE__ */ new Map();
|
|
1584
|
-
for (const [value, count] of index.facetValueCounts(bitset())) {
|
|
1585
|
-
counts.set(String(value), count);
|
|
1586
|
-
}
|
|
1587
|
-
return counts;
|
|
1588
|
-
}
|
|
1589
|
-
}
|
|
1590
|
-
return countValuesFromDocuments(state, fieldPath, matched);
|
|
1591
|
-
}
|
|
1592
|
-
function computeFacets(state, matched, config, schema) {
|
|
1593
|
-
const result = {};
|
|
1594
|
-
const flatSchema = getFlatSchema(state, schema);
|
|
1595
|
-
let matchedBitset = null;
|
|
1596
|
-
const bitset = () => {
|
|
1597
|
-
if (matchedBitset === null) matchedBitset = ordinalBitsetOf(state, matched);
|
|
1598
|
-
return matchedBitset;
|
|
1599
|
-
};
|
|
1600
|
-
for (const [fieldPath, facetOpts] of Object.entries(config)) {
|
|
1601
|
-
const fieldType = flatSchema[fieldPath];
|
|
1602
|
-
if (!fieldType) continue;
|
|
1603
|
-
const valueCounts = facetOpts.ranges && (fieldType === "number" || fieldType === "number[]") ? countNumericRanges(state, fieldPath, fieldType, facetOpts.ranges, bitset, matched) : countFieldValues(state, fieldPath, fieldType, bitset, matched);
|
|
1604
|
-
const ordered = Array.from(valueCounts.entries());
|
|
1605
|
-
const sortDir = facetOpts.sort ?? "desc";
|
|
1606
|
-
ordered.sort((a, b) => (sortDir === "asc" ? a[1] - b[1] : b[1] - a[1]) || compareCodePoints(a[0], b[0]));
|
|
1607
|
-
const keep = facetOpts.limit && facetOpts.limit > 0 ? facetOpts.limit : ordered.length;
|
|
1608
|
-
const entries = ordered.slice(0, keep);
|
|
1609
|
-
let errorBound = 0;
|
|
1610
|
-
for (let index = keep; index < ordered.length; index++) {
|
|
1611
|
-
if (ordered[index][1] > errorBound) errorBound = ordered[index][1];
|
|
1612
|
-
}
|
|
1613
|
-
const values = {};
|
|
1614
|
-
for (const [key, count] of entries) {
|
|
1615
|
-
values[key] = count;
|
|
1616
|
-
}
|
|
1617
|
-
result[fieldPath] = { values, count: entries.length, errorBound };
|
|
1618
|
-
}
|
|
1619
|
-
return result;
|
|
1620
|
-
}
|
|
1621
|
-
|
|
1622
|
-
// src/geo/constants.ts
|
|
1623
|
-
var DEG_TO_RAD = Math.PI / 180;
|
|
1624
|
-
var VINCENTY_MAX_ITERATIONS = 200;
|
|
1625
|
-
var VINCENTY_CONVERGENCE_THRESHOLD = 1e-12;
|
|
1626
|
-
|
|
1627
1418
|
// src/geo/haversine.ts
|
|
1628
1419
|
var EARTH_RADIUS_METERS = 63710088e-1;
|
|
1629
1420
|
function haversineDistance(lat1, lon1, lat2, lon2) {
|
|
@@ -1638,27 +1429,6 @@ function haversineDistance(lat1, lon1, lat2, lon2) {
|
|
|
1638
1429
|
return EARTH_RADIUS_METERS * c;
|
|
1639
1430
|
}
|
|
1640
1431
|
|
|
1641
|
-
// src/geo/polygon.ts
|
|
1642
|
-
function isPointInPolygon(lat, lon, polygon) {
|
|
1643
|
-
if (polygon.length < 3) return false;
|
|
1644
|
-
let inside = false;
|
|
1645
|
-
const n = polygon.length;
|
|
1646
|
-
for (let i = 0, j = n - 1; i < n; j = i++) {
|
|
1647
|
-
const lonI = polygon[i].lon;
|
|
1648
|
-
const latI = polygon[i].lat;
|
|
1649
|
-
const lonJ = polygon[j].lon;
|
|
1650
|
-
const latJ = polygon[j].lat;
|
|
1651
|
-
if (lonI > lon !== lonJ > lon) {
|
|
1652
|
-
const slope = (latJ - latI) / (lonJ - lonI);
|
|
1653
|
-
const intersectLat = latI + slope * (lon - lonI);
|
|
1654
|
-
if (lat < intersectLat) {
|
|
1655
|
-
inside = !inside;
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
return inside;
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
1432
|
// src/geo/vincenty.ts
|
|
1663
1433
|
var WGS84_A = 6378137;
|
|
1664
1434
|
var WGS84_F = 1 / 298.257223563;
|
|
@@ -1741,9 +1511,10 @@ function createGeoIndex() {
|
|
|
1741
1511
|
},
|
|
1742
1512
|
polygonQuery(points, inside) {
|
|
1743
1513
|
const result = /* @__PURE__ */ new Set();
|
|
1514
|
+
const contains = polygonContainment(points);
|
|
1744
1515
|
for (let i = 0; i < entries.length; i++) {
|
|
1745
1516
|
const entry = entries[i];
|
|
1746
|
-
const withinPolygon =
|
|
1517
|
+
const withinPolygon = contains(entry.lat, entry.lon);
|
|
1747
1518
|
if (inside ? withinPolygon : !withinPolygon) {
|
|
1748
1519
|
result.add(entry.docId);
|
|
1749
1520
|
}
|
|
@@ -2510,7 +2281,12 @@ var METERS_PER_MI = 1609.344;
|
|
|
2510
2281
|
function convertToMeters(distance, unit) {
|
|
2511
2282
|
if (unit === "km") return distance * METERS_PER_KM;
|
|
2512
2283
|
if (unit === "mi") return distance * METERS_PER_MI;
|
|
2513
|
-
return distance;
|
|
2284
|
+
if (unit === "m") return distance;
|
|
2285
|
+
throw new NarsilError(
|
|
2286
|
+
ErrorCodes.SEARCH_INVALID_FILTER,
|
|
2287
|
+
`The engine measures a radius in "km", "mi", or "m", and "${String(unit)}" is none of them`,
|
|
2288
|
+
{ unit: String(unit) }
|
|
2289
|
+
);
|
|
2514
2290
|
}
|
|
2515
2291
|
function matchesNumericComparison(value, filter) {
|
|
2516
2292
|
if (filter.eq !== void 0 && value !== filter.eq) return false;
|
|
@@ -2522,6 +2298,27 @@ function matchesNumericComparison(value, filter) {
|
|
|
2522
2298
|
if (filter.between !== void 0 && !(value >= filter.between[0] && value <= filter.between[1])) return false;
|
|
2523
2299
|
return true;
|
|
2524
2300
|
}
|
|
2301
|
+
function holdsValue(stored, value) {
|
|
2302
|
+
return Array.isArray(stored) ? stored.includes(value) : stored === value;
|
|
2303
|
+
}
|
|
2304
|
+
function lacksValue(stored, value) {
|
|
2305
|
+
if (stored === void 0 || stored === null) return false;
|
|
2306
|
+
return Array.isArray(stored) ? !stored.includes(value) : stored !== value;
|
|
2307
|
+
}
|
|
2308
|
+
function isStringIn(values) {
|
|
2309
|
+
return (element) => typeof element === "string" && values.has(element);
|
|
2310
|
+
}
|
|
2311
|
+
function holdsStringIn(stored, values) {
|
|
2312
|
+
return Array.isArray(stored) ? stored.some(isStringIn(values)) : isStringIn(values)(stored);
|
|
2313
|
+
}
|
|
2314
|
+
function holdsNoStringIn(stored, values) {
|
|
2315
|
+
if (Array.isArray(stored)) return !stored.some(isStringIn(values));
|
|
2316
|
+
return typeof stored === "string" && !values.has(stored);
|
|
2317
|
+
}
|
|
2318
|
+
function holdsStringWhere(stored, test) {
|
|
2319
|
+
const matches = (element) => typeof element === "string" && test(element);
|
|
2320
|
+
return Array.isArray(stored) ? stored.some(matches) : matches(stored);
|
|
2321
|
+
}
|
|
2525
2322
|
|
|
2526
2323
|
// src/filters/operators/bitset.ts
|
|
2527
2324
|
function resolveBitset(bs) {
|
|
@@ -2555,7 +2352,7 @@ function applyEqBitset(value, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
|
2555
2352
|
if (fieldIndex?.type === "enum" && typeof value === "string") {
|
|
2556
2353
|
return fieldIndex.index.getDocIdsBitset(value, capacity);
|
|
2557
2354
|
}
|
|
2558
|
-
return scanToBitset(allDocsBitset, capacity, getValue, (v) => v
|
|
2355
|
+
return scanToBitset(allDocsBitset, capacity, getValue, (v) => holdsValue(v, value));
|
|
2559
2356
|
}
|
|
2560
2357
|
function applyNeBitset(value, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
2561
2358
|
if (fieldIndex?.type === "numeric" && typeof value === "number") {
|
|
@@ -2571,7 +2368,7 @@ function applyNeBitset(value, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
|
2571
2368
|
const eq = fieldIndex.index.getDocIdsBitset(value, capacity);
|
|
2572
2369
|
return bitsetAnd(all, bitsetNot(eq, capacity));
|
|
2573
2370
|
}
|
|
2574
|
-
return scanToBitset(allDocsBitset, capacity, getValue, (v) => v
|
|
2371
|
+
return scanToBitset(allDocsBitset, capacity, getValue, (v) => lacksValue(v, value));
|
|
2575
2372
|
}
|
|
2576
2373
|
function applyGtBitset(value, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
2577
2374
|
if (fieldIndex?.type === "numeric") {
|
|
@@ -2608,7 +2405,7 @@ function applyInBitset(values, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
|
2608
2405
|
return fieldIndex.index.getDocIdsInBitset(values, capacity);
|
|
2609
2406
|
}
|
|
2610
2407
|
const valSet = new Set(values);
|
|
2611
|
-
return scanToBitset(allDocsBitset, capacity, getValue, (v) =>
|
|
2408
|
+
return scanToBitset(allDocsBitset, capacity, getValue, (v) => holdsStringIn(v, valSet));
|
|
2612
2409
|
}
|
|
2613
2410
|
function applyNinBitset(values, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
2614
2411
|
if (fieldIndex?.type === "enum") {
|
|
@@ -2617,18 +2414,13 @@ function applyNinBitset(values, allDocsBitset, capacity, getValue, fieldIndex) {
|
|
|
2617
2414
|
return bitsetAnd(all, bitsetNot(matched, capacity));
|
|
2618
2415
|
}
|
|
2619
2416
|
const valSet = new Set(values);
|
|
2620
|
-
return scanToBitset(
|
|
2621
|
-
allDocsBitset,
|
|
2622
|
-
capacity,
|
|
2623
|
-
getValue,
|
|
2624
|
-
(v) => v !== void 0 && v !== null && typeof v === "string" && !valSet.has(v)
|
|
2625
|
-
);
|
|
2417
|
+
return scanToBitset(allDocsBitset, capacity, getValue, (v) => holdsNoStringIn(v, valSet));
|
|
2626
2418
|
}
|
|
2627
2419
|
function applyStartsWithBitset(prefix, allDocsBitset, capacity, getValue) {
|
|
2628
|
-
return scanToBitset(allDocsBitset, capacity, getValue, (v) =>
|
|
2420
|
+
return scanToBitset(allDocsBitset, capacity, getValue, (v) => holdsStringWhere(v, (text) => text.startsWith(prefix)));
|
|
2629
2421
|
}
|
|
2630
2422
|
function applyEndsWithBitset(suffix, allDocsBitset, capacity, getValue) {
|
|
2631
|
-
return scanToBitset(allDocsBitset, capacity, getValue, (v) =>
|
|
2423
|
+
return scanToBitset(allDocsBitset, capacity, getValue, (v) => holdsStringWhere(v, (text) => text.endsWith(suffix)));
|
|
2632
2424
|
}
|
|
2633
2425
|
function applyContainsAllBitset(values, allDocsBitset, capacity, getValue) {
|
|
2634
2426
|
return scanToBitset(allDocsBitset, capacity, getValue, (v) => {
|
|
@@ -2692,6 +2484,7 @@ function applyGeoRadiusBitset(filter, geoIndex, capacity) {
|
|
|
2692
2484
|
return bitsetFromSet(setResult, capacity);
|
|
2693
2485
|
}
|
|
2694
2486
|
function applyGeoPolygonBitset(filter, geoIndex, capacity) {
|
|
2487
|
+
requirePolygonRing(filter.points);
|
|
2695
2488
|
const setResult = geoIndex.polygonQuery(filter.points, filter.inside ?? true);
|
|
2696
2489
|
return bitsetFromSet(setResult, capacity);
|
|
2697
2490
|
}
|
|
@@ -2741,9 +2534,10 @@ function evaluateFieldFilter(fieldPath, filter, context) {
|
|
|
2741
2534
|
OPERATOR_KEYS,
|
|
2742
2535
|
(key) => `Field "${fieldPath}" is tested with "${key}", which is no filter operator`
|
|
2743
2536
|
);
|
|
2537
|
+
const f = filter;
|
|
2538
|
+
requireValidOperands(fieldPath, f, context.fieldTypes[fieldPath]);
|
|
2744
2539
|
const fieldIndex = context.fieldIndexes[fieldPath];
|
|
2745
2540
|
const getValue = (internalId) => context.getFieldValue(internalId, fieldPath);
|
|
2746
|
-
const f = filter;
|
|
2747
2541
|
const bitsets = [];
|
|
2748
2542
|
const { capacity } = context;
|
|
2749
2543
|
let allDocsBitset = null;
|
|
@@ -2915,6 +2709,7 @@ function buildFilterContext(state, schema) {
|
|
|
2915
2709
|
let cachedAllDocIds = null;
|
|
2916
2710
|
let cachedAllDocIdsBitset = null;
|
|
2917
2711
|
return {
|
|
2712
|
+
fieldTypes: flat,
|
|
2918
2713
|
fieldIndexes,
|
|
2919
2714
|
getFieldValue: (internalId, fieldPath) => getFieldValueByInternalId(state.docStore, internalId, fieldPath),
|
|
2920
2715
|
get allDocIds() {
|
|
@@ -3236,8 +3031,7 @@ function createValueStore(initialKind) {
|
|
|
3236
3031
|
get kind() {
|
|
3237
3032
|
return kind;
|
|
3238
3033
|
},
|
|
3239
|
-
set(internalId,
|
|
3240
|
-
const comparable = toComparableSortValue(value);
|
|
3034
|
+
set(internalId, comparable) {
|
|
3241
3035
|
if (kind === "number") {
|
|
3242
3036
|
if (comparable === null) {
|
|
3243
3037
|
setNumber(internalId, Number.NaN);
|
|
@@ -3307,6 +3101,12 @@ function createValueStore(initialKind) {
|
|
|
3307
3101
|
}
|
|
3308
3102
|
|
|
3309
3103
|
// src/core/partition/sort-columns/index.ts
|
|
3104
|
+
function mayHoldList(fieldType) {
|
|
3105
|
+
return fieldType === void 0 || fieldType.endsWith("[]");
|
|
3106
|
+
}
|
|
3107
|
+
function columnKeyOf(field, fieldType, mode) {
|
|
3108
|
+
return mayHoldList(fieldType) ? `${mode}:${field}` : `value:${field}`;
|
|
3109
|
+
}
|
|
3310
3110
|
function liveInternalIds(docStore) {
|
|
3311
3111
|
const ids = [];
|
|
3312
3112
|
for (const internalId of docStore.allInternalIds()) ids.push(internalId);
|
|
@@ -3324,21 +3124,22 @@ function createSortColumnSet(docStore) {
|
|
|
3324
3124
|
entry.dirty.clear();
|
|
3325
3125
|
entry.dirtyStream = null;
|
|
3326
3126
|
}
|
|
3327
|
-
function backfill(field, fieldType) {
|
|
3127
|
+
function backfill(key, field, fieldType, mode) {
|
|
3328
3128
|
const store = createValueStore(kindForFieldType(fieldType));
|
|
3329
3129
|
for (const [docId, stored] of docStore.all()) {
|
|
3330
3130
|
const internalId = docStore.getInternalId(docId);
|
|
3331
3131
|
if (internalId === void 0) continue;
|
|
3332
|
-
store.set(internalId, readSortField(stored.fields, field));
|
|
3132
|
+
store.set(internalId, toReducedSortValue(readSortField(stored.fields, field), mode));
|
|
3333
3133
|
}
|
|
3334
3134
|
const entry = {
|
|
3335
3135
|
field,
|
|
3136
|
+
mode,
|
|
3336
3137
|
store,
|
|
3337
3138
|
order: buildOrder(store, liveInternalIds(docStore), docStore.internalIdCapacity()),
|
|
3338
3139
|
dirty: /* @__PURE__ */ new Set(),
|
|
3339
3140
|
dirtyStream: null
|
|
3340
3141
|
};
|
|
3341
|
-
columns.set(
|
|
3142
|
+
columns.set(key, entry);
|
|
3342
3143
|
return entry;
|
|
3343
3144
|
}
|
|
3344
3145
|
function buildDirtyStream(entry) {
|
|
@@ -3391,13 +3192,14 @@ function createSortColumnSet(docStore) {
|
|
|
3391
3192
|
};
|
|
3392
3193
|
}
|
|
3393
3194
|
return {
|
|
3394
|
-
holds(field) {
|
|
3395
|
-
return columns.has(field);
|
|
3195
|
+
holds(field, fieldType, mode) {
|
|
3196
|
+
return columns.has(columnKeyOf(field, fieldType, mode));
|
|
3396
3197
|
},
|
|
3397
|
-
column(field, fieldType) {
|
|
3398
|
-
|
|
3198
|
+
column(field, fieldType, mode) {
|
|
3199
|
+
const key = columnKeyOf(field, fieldType, mode);
|
|
3200
|
+
let entry = columns.get(key);
|
|
3399
3201
|
if (entry === void 0) {
|
|
3400
|
-
entry = backfill(field, fieldType);
|
|
3202
|
+
entry = backfill(key, field, fieldType, mode);
|
|
3401
3203
|
} else if (entry.dirty.size > rebuildThreshold()) {
|
|
3402
3204
|
rebuild(entry);
|
|
3403
3205
|
}
|
|
@@ -3405,7 +3207,7 @@ function createSortColumnSet(docStore) {
|
|
|
3405
3207
|
},
|
|
3406
3208
|
record(internalId, document) {
|
|
3407
3209
|
for (const entry of columns.values()) {
|
|
3408
|
-
entry.store.set(internalId, readSortField(document, entry.field));
|
|
3210
|
+
entry.store.set(internalId, toReducedSortValue(readSortField(document, entry.field), entry.mode));
|
|
3409
3211
|
entry.dirty.add(internalId);
|
|
3410
3212
|
entry.dirtyStream = null;
|
|
3411
3213
|
}
|
|
@@ -3560,11 +3362,13 @@ function createStream(column, direction, anchorRank) {
|
|
|
3560
3362
|
};
|
|
3561
3363
|
}
|
|
3562
3364
|
function selectSortedPage(state, request) {
|
|
3563
|
-
const { fields, directions, fieldTypes, limit, anchorKey, anchorId, matches } = request;
|
|
3365
|
+
const { fields, directions, fieldTypes, modes, limit, anchorKey, anchorId, matches } = request;
|
|
3564
3366
|
if (limit <= 0 || fields.length === 0) return [];
|
|
3565
3367
|
const set = state.sortColumns;
|
|
3566
3368
|
if (set === null) return [];
|
|
3567
|
-
const columns = fields.map(
|
|
3369
|
+
const columns = fields.map(
|
|
3370
|
+
(field, index) => set.column(field, fieldTypes[index], modes[index] ?? defaultSortMode(directions[index] ?? "asc"))
|
|
3371
|
+
);
|
|
3568
3372
|
const resolver = state.docStore.resolver();
|
|
3569
3373
|
const leading = columns[0];
|
|
3570
3374
|
const leadingDirection = directions[0];
|
|
@@ -3606,17 +3410,18 @@ function sortedPageOf(state, request) {
|
|
|
3606
3410
|
ensureColumns(state);
|
|
3607
3411
|
return selectSortedPage(state, request);
|
|
3608
3412
|
}
|
|
3609
|
-
function sortValuesOf(state, docId, fields, fieldTypes) {
|
|
3413
|
+
function sortValuesOf(state, docId, fields, fieldTypes, modes) {
|
|
3610
3414
|
const set = state.sortColumns;
|
|
3611
3415
|
const internalId = state.docStore.getInternalId(docId);
|
|
3612
3416
|
const stored = state.docStore.get(docId);
|
|
3613
3417
|
const key = new Array(fields.length);
|
|
3614
3418
|
for (let i = 0; i < fields.length; i++) {
|
|
3615
|
-
|
|
3616
|
-
|
|
3419
|
+
const mode = modes[i] ?? "min";
|
|
3420
|
+
if (set !== null && internalId !== void 0 && set.holds(fields[i], fieldTypes[i], mode)) {
|
|
3421
|
+
key[i] = set.column(fields[i], fieldTypes[i], mode).valueOf(internalId);
|
|
3617
3422
|
continue;
|
|
3618
3423
|
}
|
|
3619
|
-
key[i] = stored === void 0 ? null :
|
|
3424
|
+
key[i] = stored === void 0 ? null : toReducedSortValue(readSortField(stored.fields, fields[i]), mode);
|
|
3620
3425
|
}
|
|
3621
3426
|
return key;
|
|
3622
3427
|
}
|
|
@@ -5647,8 +5452,8 @@ function createPartitionIndex(partitionId, trackPositions = true) {
|
|
|
5647
5452
|
sortedPage(request) {
|
|
5648
5453
|
return sortedPageOf(state, request);
|
|
5649
5454
|
},
|
|
5650
|
-
sortValues(docId, fields, fieldTypes) {
|
|
5651
|
-
return sortValuesOf(state, docId, fields, fieldTypes);
|
|
5455
|
+
sortValues(docId, fields, fieldTypes, modes) {
|
|
5456
|
+
return sortValuesOf(state, docId, fields, fieldTypes, modes);
|
|
5652
5457
|
},
|
|
5653
5458
|
applyFilters(filters, schema) {
|
|
5654
5459
|
return applyPartitionFilters(state, filters, schema);
|
|
@@ -6040,10 +5845,10 @@ function compositeSortedPage(subs, layout, request) {
|
|
|
6040
5845
|
if (merged.length > request.limit) merged.length = request.limit;
|
|
6041
5846
|
return merged;
|
|
6042
5847
|
}
|
|
6043
|
-
function compositeSortValues(subs, docId, fields, fieldTypes) {
|
|
5848
|
+
function compositeSortValues(subs, docId, fields, fieldTypes, modes) {
|
|
6044
5849
|
for (const sub of subs) {
|
|
6045
5850
|
if (sub.docStore.has(docId)) {
|
|
6046
|
-
return sortValuesOf(sub, docId, fields, fieldTypes);
|
|
5851
|
+
return sortValuesOf(sub, docId, fields, fieldTypes, modes);
|
|
6047
5852
|
}
|
|
6048
5853
|
}
|
|
6049
5854
|
return fields.map(() => null);
|
|
@@ -6268,6 +6073,7 @@ function createCompositePartition(partitionId, trackPositions = true, existingLi
|
|
|
6268
6073
|
return compositeFilterMatches(subs(), layout(), filters, schema);
|
|
6269
6074
|
},
|
|
6270
6075
|
computeFacets(matched, config, schema) {
|
|
6076
|
+
const everyValue = everyValueFacetConfig(config);
|
|
6271
6077
|
if ("ordinalBitset" in matched) {
|
|
6272
6078
|
const ordinalLayout = layout();
|
|
6273
6079
|
return mergeFacets(
|
|
@@ -6275,19 +6081,23 @@ function createCompositePartition(partitionId, trackPositions = true, existingLi
|
|
|
6275
6081
|
(sub, index) => computeFacets(
|
|
6276
6082
|
sub,
|
|
6277
6083
|
{ ordinalBitset: subBitsetView(matched.ordinalBitset, ordinalLayout, index) },
|
|
6278
|
-
|
|
6084
|
+
everyValue,
|
|
6279
6085
|
schema
|
|
6280
6086
|
)
|
|
6281
|
-
)
|
|
6087
|
+
),
|
|
6088
|
+
config
|
|
6282
6089
|
);
|
|
6283
6090
|
}
|
|
6284
|
-
return mergeFacets(
|
|
6091
|
+
return mergeFacets(
|
|
6092
|
+
subs().map((sub) => computeFacets(sub, matched, everyValue, schema)),
|
|
6093
|
+
config
|
|
6094
|
+
);
|
|
6285
6095
|
},
|
|
6286
6096
|
sortedPage(request) {
|
|
6287
6097
|
return compositeSortedPage(subs(), layout(), request);
|
|
6288
6098
|
},
|
|
6289
|
-
sortValues(docId, fields, fieldTypes) {
|
|
6290
|
-
return compositeSortValues(subs(), docId, fields, fieldTypes);
|
|
6099
|
+
sortValues(docId, fields, fieldTypes, modes) {
|
|
6100
|
+
return compositeSortValues(subs(), docId, fields, fieldTypes, modes);
|
|
6291
6101
|
},
|
|
6292
6102
|
suggestTerms(surfacePrefix, stemmedPrefix, limit) {
|
|
6293
6103
|
return compositeSuggestTerms(subs(), surfacePrefix, stemmedPrefix, limit);
|
|
@@ -6572,10 +6382,10 @@ function createPartitionManager(indexName, config, language, router, initialPart
|
|
|
6572
6382
|
if (pid === void 0) return void 0;
|
|
6573
6383
|
return partitions[pid].getRef(docId);
|
|
6574
6384
|
},
|
|
6575
|
-
sortValues(docId, fields, fieldTypes) {
|
|
6385
|
+
sortValues(docId, fields, fieldTypes, modes) {
|
|
6576
6386
|
const pid = locateDocument(docId);
|
|
6577
6387
|
if (pid === void 0) return fields.map(() => null);
|
|
6578
|
-
return partitions[pid].sortValues(docId, fields, fieldTypes);
|
|
6388
|
+
return partitions[pid].sortValues(docId, fields, fieldTypes, modes);
|
|
6579
6389
|
},
|
|
6580
6390
|
has(docId) {
|
|
6581
6391
|
return locateDocument(docId) !== void 0;
|
|
@@ -6895,6 +6705,14 @@ async function spawnNodeWorker(entryPoint, resourceLimits) {
|
|
|
6895
6705
|
return null;
|
|
6896
6706
|
}
|
|
6897
6707
|
}
|
|
6708
|
+
async function nodeThreadId() {
|
|
6709
|
+
try {
|
|
6710
|
+
const workerThreads = await import('worker_threads');
|
|
6711
|
+
return workerThreads.threadId;
|
|
6712
|
+
} catch {
|
|
6713
|
+
return 0;
|
|
6714
|
+
}
|
|
6715
|
+
}
|
|
6898
6716
|
async function isNodeMainThread() {
|
|
6899
6717
|
try {
|
|
6900
6718
|
const workerThreads = await import('worker_threads');
|
|
@@ -6904,6 +6722,21 @@ async function isNodeMainThread() {
|
|
|
6904
6722
|
}
|
|
6905
6723
|
}
|
|
6906
6724
|
|
|
6725
|
+
// src/workers/entry-point.ts
|
|
6726
|
+
var DIST_SEGMENT = "/dist/";
|
|
6727
|
+
function resolveWorkerEntry(moduleUrl, sourceDirectory, distEntry) {
|
|
6728
|
+
const distIndex = moduleUrl.lastIndexOf(DIST_SEGMENT);
|
|
6729
|
+
const entry = distIndex !== -1 ? new URL(distEntry, moduleUrl.slice(0, distIndex + DIST_SEGMENT.length)).href : sourceDirectory.test(moduleUrl) ? moduleUrl.replace(sourceDirectory, `${DIST_SEGMENT}${distEntry}`) : null;
|
|
6730
|
+
return entry === moduleUrl ? null : entry;
|
|
6731
|
+
}
|
|
6732
|
+
function missingWorkerEntry(moduleUrl) {
|
|
6733
|
+
return new NarsilError(
|
|
6734
|
+
ErrorCodes.CONFIG_INVALID,
|
|
6735
|
+
`The engine finds no worker entry beside its own module at "${moduleUrl}", which happens where a bundler folds @delali/narsil into an application bundle. Keep @delali/narsil outside the bundle, or set workers.enabled to false`,
|
|
6736
|
+
{ moduleUrl }
|
|
6737
|
+
);
|
|
6738
|
+
}
|
|
6739
|
+
|
|
6907
6740
|
// src/workers/resource-limits.ts
|
|
6908
6741
|
function workerResourceLimits() {
|
|
6909
6742
|
return { maxYoungGenerationSizeMb: WORKER_YOUNG_GENERATION_MB };
|
|
@@ -6911,14 +6744,10 @@ function workerResourceLimits() {
|
|
|
6911
6744
|
|
|
6912
6745
|
// src/vector/search-pool/spawn.ts
|
|
6913
6746
|
function resolveWorkerEntryPoint() {
|
|
6914
|
-
|
|
6915
|
-
const distIndex = base.lastIndexOf("/dist/");
|
|
6916
|
-
if (distIndex !== -1) {
|
|
6917
|
-
return new URL("vector/search-worker.mjs", base.slice(0, distIndex + 6)).href;
|
|
6918
|
-
}
|
|
6919
|
-
return base.replace(/\/src\/vector\/search-pool\/[^/]+$/, "/dist/vector/search-worker.mjs");
|
|
6747
|
+
return resolveWorkerEntry(import.meta.url, /\/src\/vector\/search-pool\/[^/]+$/, "vector/search-worker.mjs");
|
|
6920
6748
|
}
|
|
6921
6749
|
async function spawnWorker(entryPoint) {
|
|
6750
|
+
if (entryPoint === null) return null;
|
|
6922
6751
|
const runtime = detectRuntime();
|
|
6923
6752
|
if (runtime.supportsWorkerThreads) {
|
|
6924
6753
|
try {
|
|
@@ -8580,6 +8409,18 @@ function* filteredDocIds(state, filter) {
|
|
|
8580
8409
|
if (docId !== void 0) yield docId;
|
|
8581
8410
|
}
|
|
8582
8411
|
}
|
|
8412
|
+
function admittedTotal(state, filter) {
|
|
8413
|
+
return filter === void 0 ? liveSize(state) : filter.count;
|
|
8414
|
+
}
|
|
8415
|
+
function fetchedOutcome(state, results, minSimilarity, filter) {
|
|
8416
|
+
if (minSimilarity === Number.NEGATIVE_INFINITY) {
|
|
8417
|
+
return { results, matched: admittedTotal(state, filter), matchedExact: true };
|
|
8418
|
+
}
|
|
8419
|
+
return { results, matched: results.length, matchedExact: false };
|
|
8420
|
+
}
|
|
8421
|
+
function scannedOutcome(scan2) {
|
|
8422
|
+
return { results: scan2.results, matched: scan2.matched, matchedExact: true };
|
|
8423
|
+
}
|
|
8583
8424
|
function highScoreFirst(a, b) {
|
|
8584
8425
|
return b.score - a.score || compareCodePoints(a.docId, b.docId);
|
|
8585
8426
|
}
|
|
@@ -8599,12 +8440,15 @@ function scanThroughTheCore(state, query, k, metric, minSimilarity, scanned) {
|
|
|
8599
8440
|
const distances = nativeScoresOf(state.store.handles, query, metric, scanned.ordinals);
|
|
8600
8441
|
if (distances === null) return null;
|
|
8601
8442
|
const heap = createBoundedMaxHeap(highScoreFirst, k);
|
|
8443
|
+
let matched = 0;
|
|
8602
8444
|
for (let i = 0; i < scanned.ordinals.length; i++) {
|
|
8603
8445
|
if (distances[i] === Number.POSITIVE_INFINITY) continue;
|
|
8604
8446
|
const score = toScore(distances[i], metric);
|
|
8605
|
-
if (score
|
|
8447
|
+
if (score < minSimilarity) continue;
|
|
8448
|
+
matched++;
|
|
8449
|
+
heap.push({ docId: scanned.docIds[i], score });
|
|
8606
8450
|
}
|
|
8607
|
-
return heap.toSortedArray().reverse();
|
|
8451
|
+
return { results: heap.toSortedArray().reverse(), matched };
|
|
8608
8452
|
}
|
|
8609
8453
|
function bruteForceSearch(state, query, k, metric, minSimilarity, candidates) {
|
|
8610
8454
|
const scanned = liveCandidates(state, candidates);
|
|
@@ -8614,6 +8458,7 @@ function bruteForceSearch(state, query, k, metric, minSimilarity, candidates) {
|
|
|
8614
8458
|
const arenaQuery = state.store.prepareQueryArena(query);
|
|
8615
8459
|
const queryMag = arenaQuery ? arenaQuery.magnitude : magnitude(query);
|
|
8616
8460
|
const heap = createBoundedMaxHeap(highScoreFirst, k);
|
|
8461
|
+
let matched = 0;
|
|
8617
8462
|
for (let i = 0; i < scanned.docIds.length; i++) {
|
|
8618
8463
|
const docId = scanned.docIds[i];
|
|
8619
8464
|
let score;
|
|
@@ -8638,11 +8483,11 @@ function bruteForceSearch(state, query, k, metric, minSimilarity, candidates) {
|
|
|
8638
8483
|
}
|
|
8639
8484
|
}
|
|
8640
8485
|
}
|
|
8641
|
-
if (score
|
|
8642
|
-
|
|
8643
|
-
}
|
|
8486
|
+
if (score < minSimilarity) continue;
|
|
8487
|
+
matched++;
|
|
8488
|
+
heap.push({ docId, score });
|
|
8644
8489
|
}
|
|
8645
|
-
return heap.toSortedArray().reverse();
|
|
8490
|
+
return { results: heap.toSortedArray().reverse(), matched };
|
|
8646
8491
|
}
|
|
8647
8492
|
function mergeResults(hnswResults, bufferResults, k) {
|
|
8648
8493
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8688,32 +8533,38 @@ function searchWithFilter(state, query, k, options, filter) {
|
|
|
8688
8533
|
);
|
|
8689
8534
|
}
|
|
8690
8535
|
const currentLiveSize = liveSize(state);
|
|
8691
|
-
|
|
8692
|
-
if (
|
|
8536
|
+
const { metric, minSimilarity, efSearch, oversample } = options;
|
|
8537
|
+
if (currentLiveSize === 0) return { results: [], matched: 0, matchedExact: true };
|
|
8538
|
+
if (filter && filter.count === 0) return { results: [], matched: 0, matchedExact: true };
|
|
8539
|
+
if (k <= 0) return fetchedOutcome(state, [], minSimilarity, filter);
|
|
8693
8540
|
if (state.buffer.size > 0 && !state.building && !state.buildScheduled) {
|
|
8694
8541
|
scheduleBuild(state);
|
|
8695
8542
|
}
|
|
8696
|
-
const { metric, minSimilarity, efSearch, oversample } = options;
|
|
8697
|
-
if (filter && filter.count === 0) return [];
|
|
8698
8543
|
if (!state.hnsw) {
|
|
8699
8544
|
const candidates = filter ? filteredDocIds(state, filter) : allLiveDocIds(state);
|
|
8700
|
-
return bruteForceSearch(state, query, k, metric, minSimilarity, candidates);
|
|
8545
|
+
return scannedOutcome(bruteForceSearch(state, query, k, metric, minSimilarity, candidates));
|
|
8701
8546
|
}
|
|
8702
8547
|
if (filter) {
|
|
8703
8548
|
const hnswLiveSize = state.hnsw.size;
|
|
8704
8549
|
const selectivity = hnswLiveSize > 0 ? filter.count / hnswLiveSize : 1;
|
|
8705
8550
|
if (selectivity < state.filterThreshold) {
|
|
8706
|
-
|
|
8551
|
+
const scan2 = bruteForceSearch(state, query, k, metric, minSimilarity, filteredDocIds(state, filter));
|
|
8552
|
+
return scannedOutcome(scan2);
|
|
8707
8553
|
}
|
|
8708
8554
|
}
|
|
8709
8555
|
const graphOptions = { filter, efSearch, oversample };
|
|
8710
8556
|
if (state.buffer.size === 0) {
|
|
8711
8557
|
const hnswResults2 = state.hnsw.search(query, k, metric, minSimilarity, graphOptions);
|
|
8712
|
-
return
|
|
8558
|
+
return fetchedOutcome(
|
|
8559
|
+
state,
|
|
8560
|
+
hnswResults2.map((r) => ({ docId: r.docId, score: r.score })),
|
|
8561
|
+
minSimilarity,
|
|
8562
|
+
filter
|
|
8563
|
+
);
|
|
8713
8564
|
}
|
|
8714
8565
|
const hnswResults = state.hnsw.search(query, k, metric, minSimilarity, graphOptions).map((r) => ({ docId: r.docId, score: r.score }));
|
|
8715
|
-
const
|
|
8716
|
-
return mergeResults(hnswResults,
|
|
8566
|
+
const buffered = bruteForceSearch(state, query, k, metric, minSimilarity, bufferCandidates(state, filter));
|
|
8567
|
+
return fetchedOutcome(state, mergeResults(hnswResults, buffered.results, k), minSimilarity, filter);
|
|
8717
8568
|
}
|
|
8718
8569
|
|
|
8719
8570
|
// src/vector/vector-index/index.ts
|
|
@@ -8888,7 +8739,7 @@ function createVectorIndex(fieldName, dimension, config, workerCopies = VECTOR_W
|
|
|
8888
8739
|
efSearch: options.efSearch,
|
|
8889
8740
|
oversample: options.oversample
|
|
8890
8741
|
});
|
|
8891
|
-
if (viaWorkerCopy !== null) return viaWorkerCopy;
|
|
8742
|
+
if (viaWorkerCopy !== null) return fetchedOutcome(state, viaWorkerCopy, options.minSimilarity, filter);
|
|
8892
8743
|
if (confined && state.revision !== filterRevision) {
|
|
8893
8744
|
filter = filterForOptions(state, options);
|
|
8894
8745
|
}
|
|
@@ -10897,20 +10748,26 @@ function bruteForceOrdinals(state, docIdOf, query, k, metric, minSimilarity, fil
|
|
|
10897
10748
|
}
|
|
10898
10749
|
const distances = nativeScoresOf(state.store.handles, query, metric, ordinals) ?? distancesInTypeScript(state, query, metric, ordinals);
|
|
10899
10750
|
const heap = createBoundedMaxHeap(bestFirst, k);
|
|
10751
|
+
let matched = 0;
|
|
10900
10752
|
for (let i = 0; i < ordinals.length; i++) {
|
|
10901
10753
|
if (distances[i] === Number.POSITIVE_INFINITY) continue;
|
|
10902
10754
|
const score = toScore(distances[i], metric);
|
|
10903
|
-
if (score
|
|
10755
|
+
if (score < minSimilarity) continue;
|
|
10756
|
+
matched++;
|
|
10757
|
+
heap.push({ ord: ordinals[i], score, docId: docIds[i] });
|
|
10904
10758
|
}
|
|
10905
|
-
return heap.toSortedArray().reverse();
|
|
10759
|
+
return { hits: heap.toSortedArray().reverse(), matched, matchedExact: true };
|
|
10906
10760
|
}
|
|
10907
10761
|
function createSharedVectorSearcher(options) {
|
|
10908
10762
|
const { fieldName, view, holdsDocument } = options;
|
|
10909
10763
|
function filterForDocIds(allowed) {
|
|
10910
10764
|
const filter = createOrdinalFilter(view.store.slots);
|
|
10765
|
+
const graph = view.graph;
|
|
10911
10766
|
for (const docId of allowed) {
|
|
10912
10767
|
const ordinal = view.ordinalOf(docId);
|
|
10913
|
-
if (ordinal
|
|
10768
|
+
if (ordinal === void 0) continue;
|
|
10769
|
+
if (graph !== null && isTombstoned(graph, ordinal)) continue;
|
|
10770
|
+
addToOrdinalFilter(filter, ordinal);
|
|
10914
10771
|
}
|
|
10915
10772
|
return filter;
|
|
10916
10773
|
}
|
|
@@ -10937,7 +10794,11 @@ function createSharedVectorSearcher(options) {
|
|
|
10937
10794
|
if (graph !== null && filter !== void 0 && liveSize2 > 0 && filter.count / liveSize2 < view.handles.filterThreshold) {
|
|
10938
10795
|
return bruteForceOrdinals(graph, view.docIdOf, query, k, metric, minSimilarity, filter);
|
|
10939
10796
|
}
|
|
10940
|
-
|
|
10797
|
+
const hits = view.searchOrdinals(query, k, metric, minSimilarity, { filter, efSearch, oversample });
|
|
10798
|
+
if (minSimilarity === Number.NEGATIVE_INFINITY) {
|
|
10799
|
+
return { hits, matched: filter === void 0 ? liveSize2 : filter.count, matchedExact: true };
|
|
10800
|
+
}
|
|
10801
|
+
return { hits, matched: hits.length, matchedExact: false };
|
|
10941
10802
|
}
|
|
10942
10803
|
return {
|
|
10943
10804
|
fieldName,
|
|
@@ -10953,15 +10814,22 @@ function createSharedVectorSearcher(options) {
|
|
|
10953
10814
|
);
|
|
10954
10815
|
}
|
|
10955
10816
|
const filter = filterFor(searchOptions);
|
|
10956
|
-
if (filter !== void 0 && filter.count === 0)
|
|
10957
|
-
|
|
10817
|
+
if (filter !== void 0 && filter.count === 0) {
|
|
10818
|
+
return Promise.resolve({ results: [], matched: 0, matchedExact: true });
|
|
10819
|
+
}
|
|
10820
|
+
const scanned = hitsFor(query, k, searchOptions, filter);
|
|
10958
10821
|
const results = [];
|
|
10959
|
-
for (const hit of hits) {
|
|
10822
|
+
for (const hit of scanned.hits) {
|
|
10960
10823
|
const docId = view.docIdOf(hit.ord);
|
|
10961
10824
|
if (docId === void 0 || !holdsDocument(docId)) continue;
|
|
10962
10825
|
results.push({ docId, score: hit.score });
|
|
10963
10826
|
}
|
|
10964
|
-
|
|
10827
|
+
const holdsEveryHit = results.length === scanned.hits.length;
|
|
10828
|
+
return Promise.resolve({
|
|
10829
|
+
results,
|
|
10830
|
+
matched: scanned.matched,
|
|
10831
|
+
matchedExact: scanned.matchedExact && holdsEveryHit
|
|
10832
|
+
});
|
|
10965
10833
|
}
|
|
10966
10834
|
};
|
|
10967
10835
|
}
|
|
@@ -11297,4 +11165,4 @@ function createDirectExecutor(options) {
|
|
|
11297
11165
|
};
|
|
11298
11166
|
}
|
|
11299
11167
|
|
|
11300
|
-
export { CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, NO_LIVE_VECTOR_AT_POSITION, SHUTDOWN_TIMEOUT_MS, VECTOR_FILE_MAX_VECTORS, buildSegmentPayload, countDead, createCompositePartition, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, deadBitsWhere, deadBytesFor, decodeVectorFilePayload, decodeVectorGraphPayload, decodeVectorIndexParts, deserializeMetadata, deserializePayloadV1, deserializePayloadV2, documentsOfPayloadV2, encodeSegmentState, freezeSegmentShared, generateId, getLanguage,
|
|
11168
|
+
export { CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, NO_LIVE_VECTOR_AT_POSITION, SHUTDOWN_TIMEOUT_MS, VECTOR_FILE_MAX_VECTORS, buildSegmentPayload, countDead, createCompositePartition, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, deadBitsWhere, deadBytesFor, decodeVectorFilePayload, decodeVectorGraphPayload, decodeVectorIndexParts, deserializeMetadata, deserializePayloadV1, deserializePayloadV2, documentsOfPayloadV2, encodeSegmentState, freezeSegmentShared, generateId, getLanguage, getStopWords, getTokenizer, hasStopWords, hasTokenizer, isCompositePartition, isNodeMainThread, mergeFrozenSegments, missingWorkerEntry, nodeThreadId, readHeapStatistics, registerLanguage, registerStopWords, registerTokenizer, resolveIndexAnalysis, resolvePartitionInsertOptions, resolveRequestThreadCount, resolveWorkerCount, resolveWorkerEntry, serializeMetadata, spawnNodeWorker, splitWorkerBudget, workerResourceLimits };
|