diff --git a/mem0-ts/src/oss/src/tests/milvus.test.ts b/mem0-ts/src/oss/src/tests/milvus.test.ts index 7643b1055..a2c0184e4 100644 --- a/mem0-ts/src/oss/src/tests/milvus.test.ts +++ b/mem0-ts/src/oss/src/tests/milvus.test.ts @@ -267,6 +267,36 @@ describe("Milvus vector store (TS OSS SDK)", () => { }); }); + it("skips a wildcard '*' filter value and keeps the rest", async () => { + const client = new FakeMilvusClient({ existing: ["mem0"] }); + client.searchResponse = { results: [] }; + const store = makeStore(client, { metricType: "COSINE" }); + await store.initialize(); + + // "*" means match-any: it must be dropped, not emitted as `== "*"` (which + // matches nothing), leaving only the real agent_id clause. + await store.search([0.1, 0.2, 0.3], 5, { + user_id: "*", + agent_id: "a1", + }); + + const searchCall = client.calls.find((c) => c.method === "search")!; + expect(searchCall.args.filter).toBe('(metadata["agent_id"] == "a1")'); + }); + + it("omits the filter entirely when every value is a wildcard", async () => { + const client = new FakeMilvusClient({ existing: ["mem0"] }); + const store = makeStore(client); + await store.initialize(); + + await store.list({ user_id: "*" }); + + // All clauses dropped, so list() falls back to its match-all "" filter + // rather than a literal `(metadata["user_id"] == "*")` that matches nothing. + const queryCall = client.calls.filter((c) => c.method === "query").pop()!; + expect(queryCall.args.filter).toBe(""); + }); + it("normalises L2 distances into a 0..1 similarity score", async () => { const client = new FakeMilvusClient({ existing: ["mem0"] }); client.searchResponse = { diff --git a/mem0-ts/src/oss/src/vector_stores/milvus.ts b/mem0-ts/src/oss/src/vector_stores/milvus.ts index 284e9e08a..3f5d9a790 100644 --- a/mem0-ts/src/oss/src/vector_stores/milvus.ts +++ b/mem0-ts/src/oss/src/vector_stores/milvus.ts @@ -235,6 +235,13 @@ export class Milvus implements VectorStore { if (!Milvus.SAFE_FILTER_KEY.test(key)) { throw new Error(`Invalid filter key: ${JSON.stringify(key)}`); } + if (value === "*") { + // Wildcard - match any value. Milvus has no direct wildcard, so skip + // the clause rather than emitting a literal `== "*"` that matches + // nothing. Mirrors the Python provider (#6187) and the chroma/pinecone + // stores. + continue; + } if (typeof value === "string") { // Escape backslashes before quotes so a value can't break out of the // string literal (order matters, exactly as in the Python provider).