From f7b4e94231626f2dfb0f2b4edc2cb684b9e8b974 Mon Sep 17 00:00:00 2001
From: Thuc Pham <51660321+thucpn@users.noreply.github.com>
Date: Mon, 30 Sep 2024 17:04:43 +0700
Subject: [PATCH] feat: add filters for pinecone (#1272)

---
 .changeset/breezy-donkeys-buy.md              |  5 ++
 .../src/vector-store/PineconeVectorStore.ts   | 62 ++++++++++++++++---
 2 files changed, 60 insertions(+), 7 deletions(-)
 create mode 100644 .changeset/breezy-donkeys-buy.md

diff --git a/.changeset/breezy-donkeys-buy.md b/.changeset/breezy-donkeys-buy.md
new file mode 100644
index 000000000..73573b582
--- /dev/null
+++ b/.changeset/breezy-donkeys-buy.md
@@ -0,0 +1,5 @@
+---
+"llamaindex": patch
+---
+
+feat: add filters for pinecone
diff --git a/packages/llamaindex/src/vector-store/PineconeVectorStore.ts b/packages/llamaindex/src/vector-store/PineconeVectorStore.ts
index 503c3b1b0..ea4169f84 100644
--- a/packages/llamaindex/src/vector-store/PineconeVectorStore.ts
+++ b/packages/llamaindex/src/vector-store/PineconeVectorStore.ts
@@ -1,4 +1,6 @@
 import {
+  FilterCondition,
+  FilterOperator,
   VectorStoreBase,
   type IEmbedModel,
   type MetadataFilter,
@@ -198,14 +200,60 @@ export class PineconeVectorStore
   }
 
   toPineconeFilter(stdFilters?: MetadataFilters) {
-    return stdFilters?.filters?.reduce((carry: any, item: MetadataFilter) => {
-      // Use MetadataFilter with EQ operator to replace ExactMatchFilter
-      // TODO: support filter with other operators
-      if (item.operator === "==") {
-        carry[item.key] = item.value;
+    if (!stdFilters) return undefined;
+
+    const transformCondition = (
+      condition: `${FilterCondition}` = "and",
+    ): string => {
+      if (condition === "and") return "$and";
+      if (condition === "or") return "$or";
+      throw new Error(`Filter condition ${condition} not supported`);
+    };
+
+    const transformOperator = (operator: `${FilterOperator}`): string => {
+      switch (operator) {
+        case "!=":
+          return "$ne";
+        case "==":
+          return "$eq";
+        case ">":
+          return "$gt";
+        case "<":
+          return "$lt";
+        case ">=":
+          return "$gte";
+        case "<=":
+          return "$lte";
+        case "in":
+          return "$in";
+        case "nin":
+          return "$nin";
+        default:
+          throw new Error(`Filter operator ${operator} not supported`);
       }
-      return carry;
-    }, {});
+    };
+
+    const convertFilterItem = (filter: MetadataFilter) => {
+      return {
+        [filter.key]: {
+          [transformOperator(filter.operator)]: filter.value,
+        },
+      };
+    };
+
+    const convertFilter = (filter: MetadataFilters) => {
+      const filtersList = filter.filters
+        .map((f) => convertFilterItem(f))
+        .filter((f) => Object.keys(f).length > 0);
+
+      if (filtersList.length === 0) return undefined;
+      if (filtersList.length === 1) return filtersList[0];
+
+      const condition = transformCondition(filter.condition);
+      return { [condition]: filtersList };
+    };
+
+    return convertFilter(stdFilters);
   }
 
   textFromResultRow(row: ScoredPineconeRecord<Metadata>): string {
-- 
GitLab