mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-20 02:53:50 -04:00
feat: add is_empty operator for filtering vector store (#1107)
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"llamaindex": patch
|
||||
"@llamaindex/llamaindex-test": patch
|
||||
---
|
||||
|
||||
Add is_empty operator for filtering vector store
|
||||
@@ -273,7 +273,7 @@ export class PGVectorStore
|
||||
const paramIndex = params.length + 1;
|
||||
whereClauses.push(`metadata->>'${filter.key}' = $${paramIndex}`);
|
||||
// TODO: support filter with other operators
|
||||
if (!Array.isArray(filter.value)) {
|
||||
if (!Array.isArray(filter.value) && filter.value) {
|
||||
params.push(filter.value);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ type MetadataValue = Record<string, any>;
|
||||
|
||||
// Mapping of filter operators to metadata filter functions
|
||||
const OPERATOR_TO_FILTER: {
|
||||
[key in FilterOperator]: (
|
||||
[key in FilterOperator]?: (
|
||||
{ key, value }: MetadataFilter,
|
||||
metadata: MetadataValue,
|
||||
) => boolean;
|
||||
@@ -94,7 +94,20 @@ const buildFilterFn = (
|
||||
const queryCondition = condition || "and"; // default to and
|
||||
|
||||
const itemFilterFn = (filter: MetadataFilter): boolean => {
|
||||
if (metadata[filter.key] === undefined) return false; // always return false if the metadata key is not present
|
||||
if (filter.operator === FilterOperator.IS_EMPTY) {
|
||||
// for `is_empty` operator, return true if the metadata key is not present or the value is empty
|
||||
const value = metadata[filter.key];
|
||||
return (
|
||||
value === undefined ||
|
||||
value === null ||
|
||||
value === "" ||
|
||||
(Array.isArray(value) && value.length === 0)
|
||||
);
|
||||
}
|
||||
if (metadata[filter.key] === undefined) {
|
||||
// for other operators, always return false if the metadata key is not present
|
||||
return false;
|
||||
}
|
||||
const metadataLookupFn = OPERATOR_TO_FILTER[filter.operator];
|
||||
if (!metadataLookupFn)
|
||||
throw new Error(`Unsupported operator: ${filter.operator}`);
|
||||
|
||||
@@ -33,6 +33,7 @@ export enum FilterOperator {
|
||||
ALL = "all", // Contains all (array of strings)
|
||||
TEXT_MATCH = "text_match", // full text match (allows you to search for a specific substring, token or phrase within the text field)
|
||||
CONTAINS = "contains", // metadata array contains value (string or number)
|
||||
IS_EMPTY = "is_empty", // the field is not exist or empty (null or empty array)
|
||||
}
|
||||
|
||||
export enum FilterCondition {
|
||||
@@ -44,7 +45,7 @@ export type MetadataFilterValue = string | number | string[] | number[];
|
||||
|
||||
export interface MetadataFilter {
|
||||
key: string;
|
||||
value: MetadataFilterValue;
|
||||
value?: MetadataFilterValue;
|
||||
operator: `${FilterOperator}`; // ==, any, all,...
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ export function metadataDictToNode(
|
||||
}
|
||||
|
||||
export const parsePrimitiveValue = (
|
||||
value: MetadataFilterValue,
|
||||
value?: MetadataFilterValue,
|
||||
): string | number => {
|
||||
if (typeof value !== "number" && typeof value !== "string") {
|
||||
throw new Error("Value must be a string or number");
|
||||
@@ -89,7 +89,7 @@ export const parsePrimitiveValue = (
|
||||
};
|
||||
|
||||
export const parseArrayValue = (
|
||||
value: MetadataFilterValue,
|
||||
value?: MetadataFilterValue,
|
||||
): string[] | number[] => {
|
||||
const isPrimitiveArray =
|
||||
Array.isArray(value) &&
|
||||
|
||||
@@ -256,6 +256,18 @@ describe("SimpleVectorStore", () => {
|
||||
},
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
title: "Filter IS_EMPTY",
|
||||
filters: {
|
||||
filters: [
|
||||
{
|
||||
key: "not-exist-key",
|
||||
operator: "is_empty",
|
||||
},
|
||||
],
|
||||
},
|
||||
expected: 3,
|
||||
},
|
||||
{
|
||||
title: "Filter OR",
|
||||
filters: {
|
||||
|
||||
Reference in New Issue
Block a user