Skip to content

Commit f613276

Browse files
authoredJan 10, 2025··
Add set and range filters to filter validation when using Wrangler CLI (#7592)
1 parent c63f1b0 commit f613276

File tree

4 files changed

+40
-33
lines changed

4 files changed

+40
-33
lines changed
 

‎.changeset/lemon-years-sniff.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
New filter validation logic supporting set and range queries in Vectorize CLI

‎packages/wrangler/src/__tests__/vectorize/vectorize.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -727,11 +727,11 @@ describe("vectorize commands", () => {
727727
describe("vectorize query filter", () => {
728728
it("should parse correctly", async () => {
729729
let jsonString =
730-
'{ "p1": "abc", "p2": { "$ne": true }, "p3": 10, "p4": false, "nested.p5": "abcd" }'; // Successful parse
730+
'{ "p1": "abc", "p2": { "$ne": true }, "p3": 10, "p4": false, "nested.p5": "abcd", "p6": { "$in": ["a", 3, 4] }, "p7": {"$gt": 4, "$lte": "aaa"} }'; // Successful parse
731731
expect(
732732
JSON.stringify(validateQueryFilter(JSON.parse(jsonString)))
733733
).toMatchInlineSnapshot(
734-
`"{\\"p1\\":\\"abc\\",\\"p2\\":{\\"$ne\\":true},\\"p3\\":10,\\"p4\\":false,\\"nested.p5\\":\\"abcd\\"}"`
734+
`"{\\"p1\\":\\"abc\\",\\"p2\\":{\\"$ne\\":true},\\"p3\\":10,\\"p4\\":false,\\"nested.p5\\":\\"abcd\\",\\"p6\\":{\\"$in\\":[\\"a\\",3,4]},\\"p7\\":{\\"$gt\\":4,\\"$lte\\":\\"aaa\\"}}"`
735735
);
736736

737737
jsonString =

‎packages/wrangler/src/vectorize/query.ts

+23-29
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ import type {
88
} from "../yargs-types";
99
import type {
1010
VectorizeMatches,
11-
VectorizeMetadataFilterInnerValue,
1211
VectorizeMetadataFilterValue,
1312
VectorizeMetadataRetrievalLevel,
1413
VectorizeQueryOptions,
1514
VectorizeVectorMetadataFilter,
1615
VectorizeVectorMetadataFilterOp,
17-
VectorizeVectorMetadataValue,
1816
} from "./types";
1917

2018
export function options(yargs: CommonYargsArgv) {
@@ -155,6 +153,12 @@ export async function handler(
155153
logger.log(JSON.stringify(res, null, 2));
156154
}
157155

156+
function validateQueryFilterInnerValue(
157+
innerValue: VectorizeMetadataFilterValue
158+
) {
159+
return ["string", "number", "boolean"].includes(typeof innerValue);
160+
}
161+
158162
export function validateQueryFilter(
159163
input: object
160164
): VectorizeVectorMetadataFilter | null {
@@ -176,7 +180,7 @@ export function validateQueryFilter(
176180
for (const field in parsedObj) {
177181
if (Object.prototype.hasOwnProperty.call(parsedObj, field)) {
178182
const value = (
179-
parsedObj as Record<string, VectorizeMetadataFilterValue>
183+
parsedObj as Record<string, VectorizeVectorMetadataFilter>
180184
)[field];
181185

182186
if (Array.isArray(value)) {
@@ -186,38 +190,28 @@ export function validateQueryFilter(
186190

187191
if (typeof value === "object" && value !== null) {
188192
// Handle nested objects
189-
const innerObj: Partial<{
190-
[Op in VectorizeVectorMetadataFilterOp]?: Exclude<
191-
VectorizeVectorMetadataValue,
192-
string[]
193-
> | null;
194-
}> = {};
193+
const innerObj: VectorizeVectorMetadataFilter = {};
195194
let validInnerObj = true;
196195

197196
for (const op in value) {
198197
if (Object.prototype.hasOwnProperty.call(value, op)) {
199-
if (!["$eq", "$ne"].includes(op)) {
200-
// Skip objects with invalid operators
201-
validInnerObj = false;
202-
break;
203-
}
204-
const innerValue = (value as VectorizeMetadataFilterInnerValue)[
205-
op as VectorizeVectorMetadataFilterOp
206-
];
207-
if (Array.isArray(innerValue)) {
208-
// Skip arrays in nested objects
209-
validInnerObj = false;
210-
break;
211-
}
212-
if (
213-
typeof innerValue === "object" &&
214-
innerValue !== null &&
215-
Object.keys(innerValue).length === 0
216-
) {
217-
// Skip empty objects in nested objects
198+
const innerValue = value[op];
199+
if (["$eq", "$ne", "$lt", "$lte", "$gt", "gte"].includes(op)) {
200+
if (!validateQueryFilterInnerValue(innerValue)) {
201+
validInnerObj = false;
202+
}
203+
} else if (["$in", "$nin"].includes(op)) {
204+
if (!Array.isArray(innerValue)) {
205+
validInnerObj = false;
206+
} else {
207+
if (!innerValue.every(validateQueryFilterInnerValue)) {
208+
validInnerObj = false;
209+
}
210+
}
211+
} else {
218212
validInnerObj = false;
219-
break;
220213
}
214+
221215
innerObj[op as VectorizeVectorMetadataFilterOp] = innerValue;
222216
}
223217
}

‎packages/wrangler/src/vectorize/types.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,19 @@ export type VectorFloatArray = Float32Array | Float64Array;
2525
*
2626
* This list is expected to grow as support for more operations are released.
2727
*/
28-
export type VectorizeVectorMetadataFilterOp = "$eq" | "$ne";
28+
export type VectorizeMetadataFilterEqualityOp = "$eq" | "$ne";
29+
export type VectorizeMetadataFilterSetOp = "$in" | "$nin";
30+
export type VectorizeMetadataFilterRangeOp = "$lt" | "$lte" | "$gt" | "$gte";
31+
32+
export type VectorizeVectorMetadataFilterOp =
33+
| VectorizeMetadataFilterEqualityOp
34+
| VectorizeMetadataFilterSetOp
35+
| VectorizeMetadataFilterRangeOp;
2936

3037
export type VectorizeMetadataFilterInnerValue = Record<
3138
VectorizeVectorMetadataFilterOp,
32-
Exclude<VectorizeVectorMetadataValue, string[]>
39+
| Exclude<VectorizeVectorMetadataValue, string[]>
40+
| Exclude<VectorizeVectorMetadataValue, string[]>[]
3341
>;
3442

3543
export type VectorizeMetadataFilterValue =

0 commit comments

Comments
 (0)
Please sign in to comment.