@soulcraft/brainy 5.7.8 → 5.7.9

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/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [5.7.9](https://github.com/soulcraftlabs/brainy/compare/v5.7.8...v5.7.9) (2025-11-13)
6
+
7
+ - fix: implement exists: false and missing operators in MetadataIndexManager (b0f72ef)
8
+
9
+
5
10
  ### [5.7.8](https://github.com/soulcraftlabs/brainy/compare/v5.7.7...v5.7.8) (2025-11-13)
6
11
 
7
12
  - fix: reconstruct Map from JSON for HNSW connections (v5.7.8 hotfix) (f6f2717)
@@ -1322,7 +1322,8 @@ export class MetadataIndexManager {
1322
1322
  // exists: boolean - check if field exists (any value)
1323
1323
  case 'exists':
1324
1324
  if (operand) {
1325
- // Get all IDs that have this field (any value) from chunked sparse index with roaring bitmaps (v3.43.0)
1325
+ // exists: true - Get all IDs that have this field (any value)
1326
+ // v3.43.0: From chunked sparse index with roaring bitmaps
1326
1327
  // v3.44.1: Now fully lazy-loaded via UnifiedCache (no local sparseIndices Map)
1327
1328
  const allIntIds = new Set();
1328
1329
  // Load sparse index via UnifiedCache (lazy loading)
@@ -1344,6 +1345,76 @@ export class MetadataIndexManager {
1344
1345
  // Convert integer IDs back to UUIDs
1345
1346
  fieldResults = this.idMapper.intsIterableToUuids(allIntIds);
1346
1347
  }
1348
+ else {
1349
+ // exists: false - Get all IDs that DON'T have this field
1350
+ // v5.7.9: Fixed excludeVFS bug (was returning empty array)
1351
+ const allItemIds = await this.getAllIds();
1352
+ const existsIntIds = new Set();
1353
+ // Get IDs that HAVE this field
1354
+ const sparseIndex = await this.loadSparseIndex(field);
1355
+ if (sparseIndex) {
1356
+ for (const chunkId of sparseIndex.getAllChunkIds()) {
1357
+ const chunk = await this.chunkManager.loadChunk(field, chunkId);
1358
+ if (chunk) {
1359
+ for (const bitmap of chunk.entries.values()) {
1360
+ for (const intId of bitmap) {
1361
+ existsIntIds.add(intId);
1362
+ }
1363
+ }
1364
+ }
1365
+ }
1366
+ }
1367
+ // Convert to UUIDs and subtract from all IDs
1368
+ const existsUuids = this.idMapper.intsIterableToUuids(existsIntIds);
1369
+ const existsSet = new Set(existsUuids);
1370
+ fieldResults = allItemIds.filter(id => !existsSet.has(id));
1371
+ }
1372
+ break;
1373
+ // ===== MISSING OPERATOR =====
1374
+ // missing: boolean - equivalent to exists: !boolean (for compatibility with metadataFilter.ts)
1375
+ case 'missing':
1376
+ // missing: true is equivalent to exists: false
1377
+ // missing: false is equivalent to exists: true
1378
+ // v5.7.9: Added for API consistency with in-memory metadataFilter
1379
+ if (operand) {
1380
+ // missing: true - field does NOT exist (same as exists: false)
1381
+ const allItemIds = await this.getAllIds();
1382
+ const existsIntIds = new Set();
1383
+ const sparseIndex = await this.loadSparseIndex(field);
1384
+ if (sparseIndex) {
1385
+ for (const chunkId of sparseIndex.getAllChunkIds()) {
1386
+ const chunk = await this.chunkManager.loadChunk(field, chunkId);
1387
+ if (chunk) {
1388
+ for (const bitmap of chunk.entries.values()) {
1389
+ for (const intId of bitmap) {
1390
+ existsIntIds.add(intId);
1391
+ }
1392
+ }
1393
+ }
1394
+ }
1395
+ }
1396
+ const existsUuids = this.idMapper.intsIterableToUuids(existsIntIds);
1397
+ const existsSet = new Set(existsUuids);
1398
+ fieldResults = allItemIds.filter(id => !existsSet.has(id));
1399
+ }
1400
+ else {
1401
+ // missing: false - field DOES exist (same as exists: true)
1402
+ const allIntIds = new Set();
1403
+ const sparseIndex = await this.loadSparseIndex(field);
1404
+ if (sparseIndex) {
1405
+ for (const chunkId of sparseIndex.getAllChunkIds()) {
1406
+ const chunk = await this.chunkManager.loadChunk(field, chunkId);
1407
+ if (chunk) {
1408
+ for (const bitmap of chunk.entries.values()) {
1409
+ for (const intId of bitmap) {
1410
+ allIntIds.add(intId);
1411
+ }
1412
+ }
1413
+ }
1414
+ }
1415
+ }
1416
+ fieldResults = this.idMapper.intsIterableToUuids(allIntIds);
1417
+ }
1347
1418
  break;
1348
1419
  }
1349
1420
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "5.7.8",
3
+ "version": "5.7.9",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. Stage 3 CANONICAL: 42 nouns × 127 verbs covering 96-97% of all human knowledge.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",