@mastra/mongodb 0.13.0-alpha.2 → 0.13.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +34 -0
- package/dist/index.cjs +46 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +46 -4
- package/dist/index.js.map +1 -1
- package/dist/vector/index.d.ts +15 -0
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/vector/index.test.ts +134 -0
- package/src/vector/index.ts +69 -4
package/dist/vector/index.d.ts
CHANGED
|
@@ -73,6 +73,21 @@ export declare class MongoDBVector extends MastraVector<MongoDBVectorFilter> {
|
|
|
73
73
|
private validateVectorDimensions;
|
|
74
74
|
private setIndexDimension;
|
|
75
75
|
private transformFilter;
|
|
76
|
+
/**
|
|
77
|
+
* Transform metadata field filters to use MongoDB dot notation.
|
|
78
|
+
* Fields that are stored in the metadata subdocument need to be prefixed with 'metadata.'
|
|
79
|
+
* This handles filters from the Memory system which expects direct field access.
|
|
80
|
+
*
|
|
81
|
+
* @param filter - The filter object to transform
|
|
82
|
+
* @returns Transformed filter with metadata fields properly prefixed
|
|
83
|
+
*/
|
|
84
|
+
private transformMetadataFilter;
|
|
85
|
+
/**
|
|
86
|
+
* Determine if a field should be treated as a metadata field.
|
|
87
|
+
* Common metadata fields include thread_id, resource_id, message_id, and any field
|
|
88
|
+
* that doesn't start with underscore (MongoDB system fields).
|
|
89
|
+
*/
|
|
90
|
+
private isMetadataField;
|
|
76
91
|
}
|
|
77
92
|
export {};
|
|
78
93
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vector/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,kBAAkB,EAA4B,MAAM,SAAS,CAAC;AAI5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAGpD,MAAM,WAAW,yBAA0B,SAAQ,kBAAkB;IACnE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,UAAU,wBAAyB,SAAQ,iBAAiB,CAAC,mBAAmB,CAAC;IAC/E,cAAc,CAAC,EAAE,mBAAmB,CAAC;CACtC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAWD,qBAAa,aAAc,SAAQ,YAAY,CAAC,mBAAmB,CAAC;IAClE,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,EAAE,CAAK;IACf,OAAO,CAAC,WAAW,CAA2C;IAC9D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAe;IAClD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAc;IAChD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAc;IAChD,OAAO,CAAC,uBAAuB,CAA4C;IAC3E,OAAO,CAAC,cAAc,CAIpB;gBAEU,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,kBAAkB,CAAA;KAAE;IAQ7F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAexB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAe3B,WAAW,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAiB,EAAE,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAoGhG;;;;;;;OAOG;IACG,iBAAiB,CAAC,EACtB,SAAS,EACT,SAAiB,EACjB,eAAsB,GACvB,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBpC,MAAM,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA+DtG,KAAK,CAAC,EACV,SAAS,EACT,WAAW,EACX,IAAS,EACT,MAAM,EACN,aAAqB,EACrB,cAAc,GACf,EAAE,wBAAwB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vector/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/mongodb",
|
|
3
|
-
"version": "0.13.0
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "MongoDB provider for Mastra - includes vector store capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"tsup": "^8.5.0",
|
|
32
32
|
"typescript": "^5.8.3",
|
|
33
33
|
"vitest": "^3.2.4",
|
|
34
|
-
"@internal/
|
|
35
|
-
"@internal/
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
34
|
+
"@internal/types-builder": "0.0.2",
|
|
35
|
+
"@internal/lint": "0.0.27",
|
|
36
|
+
"@mastra/core": "0.13.0",
|
|
37
|
+
"@internal/storage-test-utils": "0.0.23"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@mastra/core": ">=0.13.0-0 <0.14.0-0"
|
package/src/vector/index.test.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createVectorTestSuite } from '@internal/storage-test-utils';
|
|
1
2
|
import { vi, describe, it, expect, beforeAll, afterAll, test } from 'vitest';
|
|
2
3
|
import { MongoDBVector } from './';
|
|
3
4
|
|
|
@@ -514,4 +515,137 @@ describe('MongoDBVector Integration Tests', () => {
|
|
|
514
515
|
expect(results.length).toBe(0);
|
|
515
516
|
});
|
|
516
517
|
});
|
|
518
|
+
|
|
519
|
+
describe('Metadata Field Filtering Bug Reproduction', () => {
|
|
520
|
+
const bugTestIndexName = 'metadata_filter_bug_test_' + Date.now();
|
|
521
|
+
|
|
522
|
+
beforeAll(async () => {
|
|
523
|
+
// Create index for bug reproduction
|
|
524
|
+
await createIndexAndWait(vectorDB, bugTestIndexName, 4, 'cosine');
|
|
525
|
+
|
|
526
|
+
// Insert vectors with thread_id and resource_id in metadata
|
|
527
|
+
// Simulating what the Memory system does
|
|
528
|
+
const vectors = [
|
|
529
|
+
[1, 0, 0, 0],
|
|
530
|
+
[0, 1, 0, 0],
|
|
531
|
+
[0, 0, 1, 0],
|
|
532
|
+
[0, 0, 0, 1],
|
|
533
|
+
];
|
|
534
|
+
|
|
535
|
+
const metadata = [
|
|
536
|
+
{ thread_id: 'thread-123', resource_id: 'resource-123', message: 'first' },
|
|
537
|
+
{ thread_id: 'thread-123', resource_id: 'resource-123', message: 'second' },
|
|
538
|
+
{ thread_id: 'thread-456', resource_id: 'resource-456', message: 'third' },
|
|
539
|
+
{ thread_id: 'thread-456', resource_id: 'resource-456', message: 'fourth' },
|
|
540
|
+
];
|
|
541
|
+
|
|
542
|
+
await vectorDB.upsert({
|
|
543
|
+
indexName: bugTestIndexName,
|
|
544
|
+
vectors,
|
|
545
|
+
metadata,
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Wait for indexing
|
|
549
|
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
afterAll(async () => {
|
|
553
|
+
await deleteIndexAndWait(vectorDB, bugTestIndexName);
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
test('filtering by thread_id WITHOUT metadata prefix works correctly', async () => {
|
|
557
|
+
// This is what Memory.rememberMessages does - passes thread_id directly
|
|
558
|
+
// Previously this would ignore the filter, but now it works correctly
|
|
559
|
+
const results = await vectorDB.query({
|
|
560
|
+
indexName: bugTestIndexName,
|
|
561
|
+
queryVector: [1, 0, 0, 0],
|
|
562
|
+
topK: 10,
|
|
563
|
+
filter: { thread_id: 'thread-123' }, // Now correctly filters by thread_id
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
// Verify the fix works - should return only documents from thread-123
|
|
567
|
+
expect(results).toHaveLength(2);
|
|
568
|
+
expect(results.every(r => r.metadata?.thread_id === 'thread-123')).toBe(true);
|
|
569
|
+
|
|
570
|
+
// Should NOT contain documents from other threads
|
|
571
|
+
const threadIds = results.map(r => r.metadata?.thread_id);
|
|
572
|
+
expect(threadIds).not.toContain('thread-456');
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
test('filtering by resource_id WITHOUT metadata prefix works correctly', async () => {
|
|
576
|
+
// This is what Memory.rememberMessages does with resource scope
|
|
577
|
+
const results = await vectorDB.query({
|
|
578
|
+
indexName: bugTestIndexName,
|
|
579
|
+
queryVector: [0, 1, 0, 0],
|
|
580
|
+
topK: 10,
|
|
581
|
+
filter: { resource_id: 'resource-123' }, // Now correctly filters by resource_id
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
// Verify the fix works - should return only documents from resource-123
|
|
585
|
+
expect(results).toHaveLength(2);
|
|
586
|
+
expect(results.every(r => r.metadata?.resource_id === 'resource-123')).toBe(true);
|
|
587
|
+
|
|
588
|
+
// Should NOT contain documents from other resources
|
|
589
|
+
const resourceIds = results.map(r => r.metadata?.resource_id);
|
|
590
|
+
expect(resourceIds).not.toContain('resource-456');
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
test('filtering WITH metadata. prefix works correctly (workaround)', async () => {
|
|
594
|
+
// This is the workaround - using metadata.thread_id
|
|
595
|
+
const results = await vectorDB.query({
|
|
596
|
+
indexName: bugTestIndexName,
|
|
597
|
+
queryVector: [1, 0, 0, 0],
|
|
598
|
+
topK: 10,
|
|
599
|
+
filter: { 'metadata.thread_id': 'thread-123' },
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
// This works correctly
|
|
603
|
+
expect(results).toHaveLength(2);
|
|
604
|
+
expect(results[0]?.metadata?.thread_id).toBe('thread-123');
|
|
605
|
+
expect(results[1]?.metadata?.thread_id).toBe('thread-123');
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
test('semantic search without filter returns all vectors (shows data exists)', async () => {
|
|
609
|
+
// Verify that the data exists and can be retrieved without filters
|
|
610
|
+
const results = await vectorDB.query({
|
|
611
|
+
indexName: bugTestIndexName,
|
|
612
|
+
queryVector: [0.5, 0.5, 0.5, 0.5],
|
|
613
|
+
topK: 10,
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
// Should return all 4 vectors
|
|
617
|
+
expect(results).toHaveLength(4);
|
|
618
|
+
|
|
619
|
+
// Verify metadata is stored correctly
|
|
620
|
+
const threadIds = results.map(r => r.metadata?.thread_id);
|
|
621
|
+
expect(threadIds).toContain('thread-123');
|
|
622
|
+
expect(threadIds).toContain('thread-456');
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
// Use the shared test suite with factory pattern
|
|
628
|
+
const vectorDB = new MongoDBVector({ uri, dbName });
|
|
629
|
+
|
|
630
|
+
createVectorTestSuite({
|
|
631
|
+
vector: vectorDB,
|
|
632
|
+
connect: async () => {
|
|
633
|
+
await vectorDB.connect();
|
|
634
|
+
await waitForAtlasSearchReady(vectorDB);
|
|
635
|
+
},
|
|
636
|
+
disconnect: async () => {
|
|
637
|
+
await vectorDB.disconnect();
|
|
638
|
+
},
|
|
639
|
+
createIndex: async (indexName: string) => {
|
|
640
|
+
await vectorDB.createIndex({ indexName, dimension: 4, metric: 'cosine' });
|
|
641
|
+
await vectorDB.waitForIndexReady({ indexName });
|
|
642
|
+
},
|
|
643
|
+
deleteIndex: async (indexName: string) => {
|
|
644
|
+
try {
|
|
645
|
+
await vectorDB.deleteIndex({ indexName });
|
|
646
|
+
} catch (error) {
|
|
647
|
+
console.error(`Error deleting index ${indexName}:`, error);
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
waitForIndexing: () => new Promise(resolve => setTimeout(resolve, 5000)),
|
|
517
651
|
});
|
package/src/vector/index.ts
CHANGED
|
@@ -302,12 +302,15 @@ export class MongoDBVector extends MastraVector<MongoDBVectorFilter> {
|
|
|
302
302
|
const mongoFilter = this.transformFilter(filter);
|
|
303
303
|
const documentMongoFilter = documentFilter ? { [this.documentFieldName]: documentFilter } : {};
|
|
304
304
|
|
|
305
|
+
// Transform metadata field filters to use dot notation
|
|
306
|
+
const transformedMongoFilter = this.transformMetadataFilter(mongoFilter);
|
|
307
|
+
|
|
305
308
|
// Combine the filters
|
|
306
309
|
let combinedFilter: any = {};
|
|
307
|
-
if (Object.keys(
|
|
308
|
-
combinedFilter = { $and: [
|
|
309
|
-
} else if (Object.keys(
|
|
310
|
-
combinedFilter =
|
|
310
|
+
if (Object.keys(transformedMongoFilter).length > 0 && Object.keys(documentMongoFilter).length > 0) {
|
|
311
|
+
combinedFilter = { $and: [transformedMongoFilter, documentMongoFilter] };
|
|
312
|
+
} else if (Object.keys(transformedMongoFilter).length > 0) {
|
|
313
|
+
combinedFilter = transformedMongoFilter;
|
|
311
314
|
} else if (Object.keys(documentMongoFilter).length > 0) {
|
|
312
315
|
combinedFilter = documentMongoFilter;
|
|
313
316
|
}
|
|
@@ -329,6 +332,9 @@ export class MongoDBVector extends MastraVector<MongoDBVectorFilter> {
|
|
|
329
332
|
|
|
330
333
|
if (candidateIds.length > 0) {
|
|
331
334
|
vectorSearch.filter = { _id: { $in: candidateIds } };
|
|
335
|
+
} else {
|
|
336
|
+
// No documents match the filter, return empty results
|
|
337
|
+
return [];
|
|
332
338
|
}
|
|
333
339
|
}
|
|
334
340
|
|
|
@@ -588,4 +594,63 @@ export class MongoDBVector extends MastraVector<MongoDBVectorFilter> {
|
|
|
588
594
|
if (!filter) return {};
|
|
589
595
|
return translator.translate(filter);
|
|
590
596
|
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Transform metadata field filters to use MongoDB dot notation.
|
|
600
|
+
* Fields that are stored in the metadata subdocument need to be prefixed with 'metadata.'
|
|
601
|
+
* This handles filters from the Memory system which expects direct field access.
|
|
602
|
+
*
|
|
603
|
+
* @param filter - The filter object to transform
|
|
604
|
+
* @returns Transformed filter with metadata fields properly prefixed
|
|
605
|
+
*/
|
|
606
|
+
private transformMetadataFilter(filter: any): any {
|
|
607
|
+
if (!filter || typeof filter !== 'object') return filter;
|
|
608
|
+
|
|
609
|
+
const transformed: any = {};
|
|
610
|
+
|
|
611
|
+
for (const [key, value] of Object.entries(filter)) {
|
|
612
|
+
// Check if this is a MongoDB operator (starts with $)
|
|
613
|
+
if (key.startsWith('$')) {
|
|
614
|
+
// For logical operators like $and, $or, recursively transform their contents
|
|
615
|
+
if (Array.isArray(value)) {
|
|
616
|
+
transformed[key] = value.map(item => this.transformMetadataFilter(item));
|
|
617
|
+
} else {
|
|
618
|
+
transformed[key] = this.transformMetadataFilter(value);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
// Check if the key already has 'metadata.' prefix
|
|
622
|
+
else if (key.startsWith('metadata.')) {
|
|
623
|
+
// Already prefixed, keep as is
|
|
624
|
+
transformed[key] = value;
|
|
625
|
+
}
|
|
626
|
+
// Check if this is a known metadata field that needs prefixing
|
|
627
|
+
else if (this.isMetadataField(key)) {
|
|
628
|
+
// Add metadata. prefix for fields stored in metadata subdocument
|
|
629
|
+
transformed[`metadata.${key}`] = value;
|
|
630
|
+
} else {
|
|
631
|
+
// Keep other fields as is
|
|
632
|
+
transformed[key] = value;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return transformed;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Determine if a field should be treated as a metadata field.
|
|
641
|
+
* Common metadata fields include thread_id, resource_id, message_id, and any field
|
|
642
|
+
* that doesn't start with underscore (MongoDB system fields).
|
|
643
|
+
*/
|
|
644
|
+
private isMetadataField(key: string): boolean {
|
|
645
|
+
// MongoDB system fields start with underscore
|
|
646
|
+
if (key.startsWith('_')) return false;
|
|
647
|
+
|
|
648
|
+
// Document-level fields that are NOT in metadata
|
|
649
|
+
const documentFields = ['_id', this.embeddingFieldName, this.documentFieldName];
|
|
650
|
+
if (documentFields.includes(key)) return false;
|
|
651
|
+
|
|
652
|
+
// Everything else is assumed to be in metadata
|
|
653
|
+
// This includes thread_id, resource_id, message_id, and any custom fields
|
|
654
|
+
return true;
|
|
655
|
+
}
|
|
591
656
|
}
|