fix(mongodb): support numeric contains filters

This commit is contained in:
zipg authored and GitHub committed 2026-09-15 01:13:34 +08:00
1 parent bd9e784d90
commit 837ea07cf3
2 files changed
+59

No files matched your search

@@ -501,9 +501,15 @@ export function buildDocumentFilterCondition(rule: DocumentFilterRule, options:
return { [rule.fieldName]: { $ne: value } };
case "like":
if (options.kind === "dynamodb") return { [rule.fieldName]: { $contains: value } };
if (options.kind === "mongodb" && mongoFilterValueIsNumeric(rule.valueType, options.sampleValue)) {
return mongoNumericContainsCondition(rule.fieldName, textValue);
}
return { [rule.fieldName]: { $regex: escapeRegexLiteral(textValue), $options: "i" } };
case "not-like":
if (options.kind === "dynamodb") return { [rule.fieldName]: { $notContains: value } };
if (options.kind === "mongodb" && mongoFilterValueIsNumeric(rule.valueType, options.sampleValue)) {
return mongoNumericContainsCondition(rule.fieldName, textValue, true);
}
return { [rule.fieldName]: { $not: { $regex: escapeRegexLiteral(textValue), $options: "i" } } };
case "greater-than":
return { [rule.fieldName]: { $gt: value } };
@@ -524,6 +530,19 @@ function escapeRegexLiteral(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function mongoFilterValueIsNumeric(valueType?: DocumentFilterValueType, sampleValue?: unknown): boolean {
if (valueType === "number" || valueType === "int32" || valueType === "int64" || valueType === "decimal128") return true;
if (typeof sampleValue === "number") return true;
if (!isPlainRecord(sampleValue)) return false;
const keys = Object.keys(sampleValue);
return keys.length === 1 && ["$numberInt", "$numberLong", "$numberDouble", "$numberDecimal"].includes(keys[0]);
}
function mongoNumericContainsCondition(fieldName: string, textValue: string, negate = false): Record<string, unknown> {
const regexMatch = { $regexMatch: { input: { $convert: { input: `$${fieldName}`, to: "string", onError: "", onNull: "" } }, regex: escapeRegexLiteral(textValue), options: "i" } };
return negate ? { $expr: { $not: [regexMatch] } } : { $expr: regexMatch };
}
export function combineDocumentFilterConditions(conditions: Record<string, unknown>[], rules: Pick<DocumentFilterRule, "conjunction">[], arrayObjectParents: Array<string | null> = []): Record<string, unknown> | null {
if (conditions.length === 0) return null;
const grouped = groupLeadingArrayObjectConditions(conditions, rules, arrayObjectParents);