@mastra/lance 1.0.0-beta.1 → 1.0.0-beta.2

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/dist/index.js CHANGED
@@ -2843,7 +2843,44 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
2843
2843
  );
2844
2844
  }
2845
2845
  }
2846
- async updateVector({ indexName, id, update }) {
2846
+ async updateVector(params) {
2847
+ const { indexName, update } = params;
2848
+ if ("id" in params && "filter" in params && params.id && params.filter) {
2849
+ throw new MastraError({
2850
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2851
+ domain: ErrorDomain.STORAGE,
2852
+ category: ErrorCategory.USER,
2853
+ text: "id and filter are mutually exclusive",
2854
+ details: { indexName }
2855
+ });
2856
+ }
2857
+ if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
2858
+ throw new MastraError({
2859
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2860
+ domain: ErrorDomain.STORAGE,
2861
+ category: ErrorCategory.USER,
2862
+ text: "Either id or filter must be provided",
2863
+ details: { indexName }
2864
+ });
2865
+ }
2866
+ if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
2867
+ throw new MastraError({
2868
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2869
+ domain: ErrorDomain.STORAGE,
2870
+ category: ErrorCategory.USER,
2871
+ text: "Cannot update with empty filter",
2872
+ details: { indexName }
2873
+ });
2874
+ }
2875
+ if (!update.vector && !update.metadata) {
2876
+ throw new MastraError({
2877
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2878
+ domain: ErrorDomain.STORAGE,
2879
+ category: ErrorCategory.USER,
2880
+ text: "No updates provided",
2881
+ details: { indexName }
2882
+ });
2883
+ }
2847
2884
  try {
2848
2885
  if (!this.lanceClient) {
2849
2886
  throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
@@ -2851,21 +2888,6 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
2851
2888
  if (!indexName) {
2852
2889
  throw new Error("indexName is required");
2853
2890
  }
2854
- if (!id) {
2855
- throw new Error("id is required");
2856
- }
2857
- } catch (err) {
2858
- throw new MastraError(
2859
- {
2860
- id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED_INVALID_ARGS",
2861
- domain: ErrorDomain.STORAGE,
2862
- category: ErrorCategory.USER,
2863
- details: { indexName, id }
2864
- },
2865
- err
2866
- );
2867
- }
2868
- try {
2869
2891
  const tables = await this.lanceClient.tableNames();
2870
2892
  for (const tableName of tables) {
2871
2893
  this.logger.debug("Checking table:" + tableName);
@@ -2875,39 +2897,66 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
2875
2897
  const hasColumn = schema.fields.some((field) => field.name === indexName);
2876
2898
  if (hasColumn) {
2877
2899
  this.logger.debug(`Found column ${indexName} in table ${tableName}`);
2878
- const existingRecord = await table.query().where(`id = '${id}'`).select(schema.fields.map((field) => field.name)).limit(1).toArray();
2879
- if (existingRecord.length === 0) {
2880
- throw new Error(`Record with id '${id}' not found in table ${tableName}`);
2900
+ let whereClause;
2901
+ if ("id" in params && params.id) {
2902
+ whereClause = `id = '${params.id}'`;
2903
+ } else if ("filter" in params && params.filter) {
2904
+ const translator = new LanceFilterTranslator();
2905
+ const processFilterKeys = (filter) => {
2906
+ const processedFilter = {};
2907
+ Object.entries(filter).forEach(([key, value]) => {
2908
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2909
+ Object.entries(value).forEach(([nestedKey, nestedValue]) => {
2910
+ processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
2911
+ });
2912
+ } else {
2913
+ processedFilter[`metadata_${key}`] = value;
2914
+ }
2915
+ });
2916
+ return processedFilter;
2917
+ };
2918
+ const prefixedFilter = processFilterKeys(params.filter);
2919
+ whereClause = translator.translate(prefixedFilter) || "";
2920
+ if (!whereClause) {
2921
+ throw new Error("Failed to translate filter to SQL");
2922
+ }
2923
+ } else {
2924
+ throw new Error("Either id or filter must be provided");
2881
2925
  }
2882
- const rowData = {
2883
- id
2884
- };
2885
- Object.entries(existingRecord[0]).forEach(([key, value]) => {
2886
- if (key !== "id" && key !== "_distance") {
2887
- if (key === indexName) {
2888
- if (!update.vector) {
2889
- if (Array.isArray(value)) {
2890
- rowData[key] = [...value];
2891
- } else if (typeof value === "object" && value !== null) {
2892
- rowData[key] = Array.from(value);
2926
+ const existingRecords = await table.query().where(whereClause).select(schema.fields.map((field) => field.name)).toArray();
2927
+ if (existingRecords.length === 0) {
2928
+ this.logger.info(`No records found matching criteria in table ${tableName}`);
2929
+ return;
2930
+ }
2931
+ const updatedRecords = existingRecords.map((record) => {
2932
+ const rowData = {};
2933
+ Object.entries(record).forEach(([key, value]) => {
2934
+ if (key !== "_distance") {
2935
+ if (key === indexName) {
2936
+ if (update.vector) {
2937
+ rowData[key] = update.vector;
2893
2938
  } else {
2894
- rowData[key] = value;
2939
+ if (Array.isArray(value)) {
2940
+ rowData[key] = [...value];
2941
+ } else if (typeof value === "object" && value !== null) {
2942
+ rowData[key] = Array.from(value);
2943
+ } else {
2944
+ rowData[key] = value;
2945
+ }
2895
2946
  }
2947
+ } else {
2948
+ rowData[key] = value;
2896
2949
  }
2897
- } else {
2898
- rowData[key] = value;
2899
2950
  }
2951
+ });
2952
+ if (update.metadata) {
2953
+ Object.entries(update.metadata).forEach(([key, value]) => {
2954
+ rowData[`metadata_${key}`] = value;
2955
+ });
2900
2956
  }
2957
+ return rowData;
2901
2958
  });
2902
- if (update.vector) {
2903
- rowData[indexName] = update.vector;
2904
- }
2905
- if (update.metadata) {
2906
- Object.entries(update.metadata).forEach(([key, value]) => {
2907
- rowData[`metadata_${key}`] = value;
2908
- });
2909
- }
2910
- await table.add([rowData], { mode: "overwrite" });
2959
+ await table.add(updatedRecords, { mode: "overwrite" });
2911
2960
  return;
2912
2961
  }
2913
2962
  } catch (err) {
@@ -2917,12 +2966,19 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
2917
2966
  }
2918
2967
  throw new Error(`No table found with column/index '${indexName}'`);
2919
2968
  } catch (error) {
2969
+ if (error instanceof MastraError) throw error;
2920
2970
  throw new MastraError(
2921
2971
  {
2922
2972
  id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED",
2923
2973
  domain: ErrorDomain.STORAGE,
2924
2974
  category: ErrorCategory.THIRD_PARTY,
2925
- details: { indexName, id, hasVector: !!update.vector, hasMetadata: !!update.metadata }
2975
+ details: {
2976
+ indexName,
2977
+ ..."id" in params && params.id && { id: params.id },
2978
+ ..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) },
2979
+ hasVector: !!update.vector,
2980
+ hasMetadata: !!update.metadata
2981
+ }
2926
2982
  },
2927
2983
  error
2928
2984
  );
@@ -2945,7 +3001,10 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
2945
3001
  id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED_INVALID_ARGS",
2946
3002
  domain: ErrorDomain.STORAGE,
2947
3003
  category: ErrorCategory.USER,
2948
- details: { indexName, id }
3004
+ details: {
3005
+ indexName,
3006
+ ...id && { id }
3007
+ }
2949
3008
  },
2950
3009
  err
2951
3010
  );
@@ -2975,7 +3034,10 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
2975
3034
  id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED",
2976
3035
  domain: ErrorDomain.STORAGE,
2977
3036
  category: ErrorCategory.THIRD_PARTY,
2978
- details: { indexName, id }
3037
+ details: {
3038
+ indexName,
3039
+ ...id && { id }
3040
+ }
2979
3041
  },
2980
3042
  error
2981
3043
  );
@@ -3006,6 +3068,109 @@ var LanceVectorStore = class _LanceVectorStore extends MastraVector {
3006
3068
  });
3007
3069
  return result;
3008
3070
  }
3071
+ async deleteVectors({ indexName, filter, ids }) {
3072
+ if (ids && filter) {
3073
+ throw new MastraError({
3074
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3075
+ domain: ErrorDomain.STORAGE,
3076
+ category: ErrorCategory.USER,
3077
+ text: "ids and filter are mutually exclusive",
3078
+ details: { indexName }
3079
+ });
3080
+ }
3081
+ if (!ids && !filter) {
3082
+ throw new MastraError({
3083
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3084
+ domain: ErrorDomain.STORAGE,
3085
+ category: ErrorCategory.USER,
3086
+ text: "Either filter or ids must be provided",
3087
+ details: { indexName }
3088
+ });
3089
+ }
3090
+ if (ids && ids.length === 0) {
3091
+ throw new MastraError({
3092
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3093
+ domain: ErrorDomain.STORAGE,
3094
+ category: ErrorCategory.USER,
3095
+ text: "Cannot delete with empty ids array",
3096
+ details: { indexName }
3097
+ });
3098
+ }
3099
+ if (filter && Object.keys(filter).length === 0) {
3100
+ throw new MastraError({
3101
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3102
+ domain: ErrorDomain.STORAGE,
3103
+ category: ErrorCategory.USER,
3104
+ text: "Cannot delete with empty filter",
3105
+ details: { indexName }
3106
+ });
3107
+ }
3108
+ try {
3109
+ if (!this.lanceClient) {
3110
+ throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
3111
+ }
3112
+ if (!indexName) {
3113
+ throw new Error("indexName is required");
3114
+ }
3115
+ const tables = await this.lanceClient.tableNames();
3116
+ for (const tableName of tables) {
3117
+ this.logger.debug("Checking table:" + tableName);
3118
+ const table = await this.lanceClient.openTable(tableName);
3119
+ try {
3120
+ const schema = await table.schema();
3121
+ const hasColumn = schema.fields.some((field) => field.name === indexName);
3122
+ if (hasColumn) {
3123
+ this.logger.debug(`Found column ${indexName} in table ${tableName}`);
3124
+ if (ids) {
3125
+ const idsConditions = ids.map((id) => `id = '${id}'`).join(" OR ");
3126
+ await table.delete(idsConditions);
3127
+ } else if (filter) {
3128
+ const translator = new LanceFilterTranslator();
3129
+ const processFilterKeys = (filter2) => {
3130
+ const processedFilter = {};
3131
+ Object.entries(filter2).forEach(([key, value]) => {
3132
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3133
+ Object.entries(value).forEach(([nestedKey, nestedValue]) => {
3134
+ processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
3135
+ });
3136
+ } else {
3137
+ processedFilter[`metadata_${key}`] = value;
3138
+ }
3139
+ });
3140
+ return processedFilter;
3141
+ };
3142
+ const prefixedFilter = processFilterKeys(filter);
3143
+ const whereClause = translator.translate(prefixedFilter);
3144
+ if (!whereClause) {
3145
+ throw new Error("Failed to translate filter to SQL");
3146
+ }
3147
+ await table.delete(whereClause);
3148
+ }
3149
+ return;
3150
+ }
3151
+ } catch (err) {
3152
+ this.logger.error(`Error checking schema for table ${tableName}:` + err);
3153
+ continue;
3154
+ }
3155
+ }
3156
+ throw new Error(`No table found with column/index '${indexName}'`);
3157
+ } catch (error) {
3158
+ if (error instanceof MastraError) throw error;
3159
+ throw new MastraError(
3160
+ {
3161
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_FAILED",
3162
+ domain: ErrorDomain.STORAGE,
3163
+ category: ErrorCategory.THIRD_PARTY,
3164
+ details: {
3165
+ indexName,
3166
+ ...filter && { filter: JSON.stringify(filter) },
3167
+ ...ids && { idsCount: ids.length }
3168
+ }
3169
+ },
3170
+ error
3171
+ );
3172
+ }
3173
+ }
3009
3174
  };
3010
3175
 
3011
3176
  export { LanceStorage, LanceVectorStore };