Skip to content

Commit 2494ed7

Browse files
community[patch]: add ?| (arrayContains) filter on metadata to PGVector search (#5381)
* add ?| (arrayContains) filter on metadata to PGVector search * fix: align to style of IN filter * Format * Update build artifacts * Format --------- Co-authored-by: jacoblee93 <[email protected]>
1 parent 28785cf commit 2494ed7

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

examples/src/indexes/vector_stores/pgvector_vectorstore/pgvector.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ const pgvectorStore = await PGVectorStore.initialize(
3434
);
3535

3636
await pgvectorStore.addDocuments([
37-
{ pageContent: "what's this", metadata: { a: 2 } },
38-
{ pageContent: "Cat drinks milk", metadata: { a: 1 } },
37+
{ pageContent: "what's this", metadata: { a: 2, b: ["tag1", "tag2"] } },
38+
{ pageContent: "Cat drinks milk", metadata: { a: 1, b: ["tag2"] } },
3939
]);
4040

4141
const results = await pgvectorStore.similaritySearch("water", 1);
@@ -84,4 +84,17 @@ console.log(results4);
8484
[ Document { pageContent: 'what's this', metadata: { a: 2 } } ]
8585
*/
8686

87+
// Filtering using arrayContains (?|) is supported
88+
const results5 = await pgvectorStore.similaritySearch("water", 1, {
89+
b: {
90+
arrayContains: ["tag1"],
91+
},
92+
});
93+
94+
console.log(results5);
95+
96+
/*
97+
[ Document { pageContent: "what's this", metadata: { a: 2, b: ['tag1', 'tag2'] } } } ]
98+
*/
99+
87100
await pgvectorStore.end();

libs/langchain-community/src/vectorstores/pgvector.ts

+12
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,18 @@ export class PGVectorStore extends VectorStore {
501501
parameters.push(..._value.in);
502502
paramCount += _value.in.length;
503503
}
504+
if (Array.isArray(_value.arrayContains)) {
505+
const placeholders = _value.arrayContains
506+
.map(
507+
(_: unknown, index: number) => `$${currentParamCount + index + 1}`
508+
)
509+
.join(",");
510+
whereClauses.push(
511+
`${this.metadataColumnName}->'${key}' ?| array[${placeholders}]`
512+
);
513+
parameters.push(..._value.arrayContains);
514+
paramCount += _value.arrayContains.length;
515+
}
504516
} else {
505517
paramCount += 1;
506518
whereClauses.push(

libs/langchain-community/src/vectorstores/tests/pgvector/pgvector.int.test.ts

+38
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,44 @@ describe("PGVectorStore", () => {
141141
expect(result3.length).toEqual(3);
142142
});
143143

144+
test("PGvector supports arrayContains (?|) in metadata filter ", async () => {
145+
const documents = [
146+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag1", "tag2"] } },
147+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag2"] } },
148+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag1"] } },
149+
];
150+
151+
await pgvectorVectorStore.addDocuments(documents);
152+
153+
const result = await pgvectorVectorStore.similaritySearch("hello", 2, {
154+
a: {
155+
arrayContains: ["tag1"],
156+
},
157+
});
158+
159+
expect(result.length).toEqual(2);
160+
expect(result).toEqual([
161+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag1", "tag2"] } },
162+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag1"] } },
163+
]);
164+
165+
const result2 = await pgvectorVectorStore.similaritySearch("hello", 2, {
166+
a: {
167+
arrayContains: ["tag2"],
168+
},
169+
});
170+
expect(result2.length).toEqual(2);
171+
expect(result2).toEqual([
172+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag1", "tag2"] } },
173+
{ pageContent: "Lorem Ipsum", metadata: { a: ["tag2"] } },
174+
]);
175+
176+
const result3 = await pgvectorVectorStore.similaritySearch("hello", 3);
177+
178+
expect(result3.length).toEqual(3);
179+
expect(result3).toEqual(documents);
180+
});
181+
144182
test("PGvector can delete document by id", async () => {
145183
try {
146184
const documents = [

0 commit comments

Comments
 (0)