FerretDB 求值查询运算符实战指南:`$mod` 取模与 `$regex` 正则匹配全解析

📅 发布时间:2026/9/24 14:47:34
FerretDB 求值查询运算符实战指南:`$mod` 取模与 `$regex` 正则匹配全解析
FerretDB 求值查询运算符实战指南$mod取模与$regex正则匹配全解析【免费下载链接】FerretDBA truly Open Source MongoDB alternative项目地址: https://gitcode.com/gh_mirrors/fe/FerretDB求值查询运算符Evaluation Query Operators是 FerretDB 查询过滤体系中的一类核心运算符它根据对字段值执行指定表达式取模运算、正则匹配等的求值结果来决定文档是否命中。本文以 FerretDB 官方文档v2.5的求值运算符章节为主体结合仓库中的兼容性测试与集成测试源码系统讲解$mod与$regex的语法、示例、边界行为与底层实现验证读完即可在 FerretDB 中直接套用。求值查询运算符是什么求值查询运算符根据对指定表达式求值的结果来返回数据。与比较运算符$eq、$gt等、逻辑运算符$and、$or等不同求值运算符的判定逻辑更偏向对字段值执行一段程序化表达式而非简单的值比较。FerretDB 官方文档evaluation-operators.md中列出的求值查询运算符包括运算符说明$mod匹配字段元素除以给定值后余数为指定值的文档$regex匹配字段满足指定正则表达式的文档其中$mod完成数值取模过滤$regex完成模式化文本匹配两者是日常查询中最常用的求值运算符。如需了解其他运算符类别可参见同目录下的 comparison-operators.md、logical-operators.md、element-operators.md、array-operators.md 与 bitwise-operators.md。准备示例数据本节所有示例都基于catalog集合。先向其中插入以下 5 条商品文档db.catalog.insertMany([ { product: bottle, price: 15, stock: 1 }, { product: spoon, price: 500, stock: 0 }, { product: cup, price: 100, stock: 14 }, { product: BoWL, price: 56, stock: 5 }, { product: boTtLe, price: 20, stock: 3 } ])数据集中刻意混入了大小写混合的BoWL、boTtLe便于演示$regex的选项flag行为stock字段包含1、0、14、5、3等不同数值便于演示$mod的取模判定。$mod 取模匹配语法$mod的语法形式为{ field: { $mod: [ divisor-value, modulus ] } }其中divisor-value是除数modulus是期望的余数。匹配的数学判定为field-value % divisor-value modulus即字段值对除数取模的结果恰好等于指定的余数时文档命中。示例筛出 stock 能被 2 整除的文档以下查询返回stock字段值能被 2 整除即余数为 0的所有文档db.catalog.find({ stock: { $mod: [2, 0] } })输出结果为response [ { _id: ObjectId(63e3ac0184f488929a3f737a), product: spoon, price: 500, stock: 0 }, { _id: ObjectId(63e3ac0184f488929a3f737b), product: cup, price: 100, stock: 14 } ]验证一下0 % 2 0、14 % 2 0均命中而1、5、3对 2 取模不为 0故不返回。边界行为与注意事项[!CAUTION]$mod表达式在以下三种情况下会返回错误数组中只有一个元素、数组元素超过两个、数组为空。 此外$mod会把小数的输入向下舍入到零例如$mod: [ 3.5 , 2 ]会按$mod: [ 3 , 2 ]执行。除了文档明确标注的上述限制仓库中的兼容性测试 query_evaluation_compat_test.goTestQueryEvaluationCompatMod还系统验证了大量边界场景可作为实际编码时的行为依据数组长度非法bson.A{}空数组、bson.A{1}单元素、bson.A{1, 2, 3}三元素均不产生匹配结果非数值输入除数或余数为字符串1、2或nil时不产生匹配结果除数为零bson.A{0, 1}以及极小非零浮点数math.SmallestNonzeroFloat64作为除数时不产生匹配结果无穷大除数或余数为math.Inf正负无穷时不产生匹配结果负数与浮点{-100, 89}、{100, -89}、{-100.5, 89.5}等正负组合与浮点组合均有对应测试浮点输入按文档规则向下取整大整数边界测试覆盖了math.MaxInt64、math.MinInt64及其浮点形式、溢出临界值如9.223372036854776833e18等场景超过 Int64 表示范围的数值不产生匹配。这些用例同时用于 FerretDB 与 MongoDB 的兼容性对比testQueryCompat说明上述行为是 FerretDB 有意对齐 MongoDB 的结果。$regex 正则匹配语法$regex提供三种等价语法形式{ field: { $regex: expression-string, $options: flag } } { field: { $regex: /expression-string/, $options: flag } } { field: /expression-string/flag }第一种使用字符串表达正则第二种使用正则字面量并显式给出$options第三种直接把正则字面量与 flag 写在一起。三种形式最终行为一致可按习惯选用。示例匹配以 b 开头的 product以下查询返回product字段值以字母 b 开头的所有文档db.catalog.find({ product: { $regex: /^b/ } })输出结果为response [ { _id: ObjectId(63e4ce469695494b86bf2b2d), product: bottle, price: 15, stock: 1 }, { _id: ObjectId(63e4ce469695494b86bf2b31), product: boTtLe, price: 20, stock: 3 } ]注意boTtLe虽然后续字符大小写混合但首字符是小写b因此同样命中BoWL首字符为大写B不命中。这说明正则默认区分大小写。$options 选项i、m、s$options是可选参数用于指定正则表达式 flag常用取值包括i大小写不敏感case-insensitivitym多行匹配multi-line matchings点号匹配任意字符包括换行dot character matching以i选项为例以下查询返回product字段值等于 bottle忽略大小写的所有文档db.catalog.find({ product: { $regex: /bottle/i } })输出结果为response [ { _id: ObjectId(63e3ac0184f488929a3f7379), product: bottle, price: 15, stock: 1 }, { _id: ObjectId(63e3ac0184f488929a3f737d), product: boTtLe, price: 20, stock: 3 } ]加了i选项后boTtLe与bottle都被视为匹配这正是大小写不敏感的直观体现。选项行为与嵌套字段的源码验证FerretDB 的集成测试 query_evaluation_test.goTestQueryEvaluationRegex对上述选项行为做了逐一验证RegexWithOption{ $regex: Pattern: 42, Options: i }命中包含 42任意大小写的字符串文档RegexStringOptionMatchCaseInsensitive以字符串形式写$regex: foo加$options: i命中含 foo、Foo 等大小写变体的文档RegexStringOptionMatchMultiline$options: m下^foo能匹配多行字符串bar\nfoo中第二行的开头RegexStringOptionMatchLineEnd$options: s下b.*foo可以跨过换行符匹配bar\nfooRegexNested{ v.foo.bar: { $regex: quz } }证明$regex支持点号嵌套字段路径。测试数据中专门插入了_id: multiline-string、值为bar\nfoo的多行字符串用于验证m与s选项的真实效果。非法正则与错误选项的处理当正则表达式本身非法、或$options携带无效 flag 时FerretDB 的行为在 query_evaluation_compat_test.goTestQueryEvaluationCompatRegexErrors中有明确覆盖包括缺失右括号g(-z]ng wrong regex、缺失右方括号、非法转义\uZ、命名捕获组(?Pname)、孤立右括号、尾部反斜杠、非法重复a**、孤立量词*、、?、非法字符类区间[z-a]、非法 Perl 语法(?z)、超大重复次数(aa){3,10001}等。这些非法模式在兼容测试中均以EmptyResult断言不产生匹配结果、不崩溃而非法选项如Options: 123同样如此。这意味着在生产使用时应先在客户端校验正则合法性避免查询静默返回空结果。结合源码理解实现位置$mod与$regex的完整行为契约主要由以下两个测试文件固化integration/query_evaluation_test.goFerretDB 侧的功能性集成测试验证$regex的正常匹配、嵌套字段、i/m/s选项integration/query_evaluation_compat_test.go与 MongoDB 的兼容性对比测试覆盖$mod的数值边界与$regex的非法输入确保 FerretDB 行为与 MongoDB 对齐。当你在 FerretDB 中运行上述find查询时查询会经由find命令的处理链路参见 internal/handler/msg_find.go最终落到底层存储引擎执行过滤。借助这两组测试开发者可以在修改相关逻辑后快速回归验证$mod、$regex的语义没有被破坏。小结$mod与$regex是 FerretDB 求值查询运算符中两种互补的能力$mod面向数值字段按取模余数精确过滤适合周期性、分批性筛选如偶数/奇数、库存分桶使用时应牢记数组必须恰好两个元素、小数会被向下取整这两个关键约束$regex面向文本字段按模式匹配过滤配合i、m、s选项可覆盖大小写不敏感、多行、跨行匹配等常见场景也可用于嵌套字段路径。两者的边界行为非法数组、非数值、非法正则、非法选项都已在 FerretDB 仓库的兼容性测试中与 MongoDB 逐一对齐验证。你可以基于本文示例数据直接在本机 FerretDB 中运行验证再将这些模式迁移到真实业务查询中。【免费下载链接】FerretDBA truly Open Source MongoDB alternative项目地址: https://gitcode.com/gh_mirrors/fe/FerretDB创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考