MongoDB 5.0.7聚合管道中$ifNull结合$in大小写不敏感匹配问题
MongoDB聚合管道嵌套数组大小写不敏感匹配问题解决
问题根源
MongoDB 5.0.7中,$in在$expr上下文里使用正则表达式时,不会对数组元素执行正则匹配逻辑——它只会检查数组中是否有元素等于这个正则对象本身,这显然和你要的大小写不敏感搜索逻辑不符,所以Query1和Query3都没返回预期结果。
解决方案
要实现嵌套数组的大小写不敏感匹配,同时兼容$ifNull处理空数组的场景,需要用$anyElementTrue+$map+$regexMatch的组合替代$in的正则用法:
1. 基础大小写不敏感匹配(替代Query1)
先遍历order.products.item数组,对每个元素做大小写不敏感正则匹配,再判断是否存在至少一个匹配成功的元素:
db.items.aggregate([ { $match: { $expr: { $anyElementTrue: { $map: { input: "$order.products.item", as: "item", in: { $regexMatch: { input: "$$item", regex: /item1/i } } } } } } } ])
2. 结合$ifNull的版本(替代Query3)
把$ifNull整合到遍历的输入参数中,处理order.products.item不存在的情况(返回空数组避免报错):
db.items.aggregate([ { $match: { $expr: { $anyElementTrue: { $map: { input: { $ifNull: ["$order.products.item", []] }, as: "item", in: { $regexMatch: { input: "$$item", regex: /item1/i } } } } } } } ])
3. 另一种写法:统一转大小写后用$in
如果不想用正则,也可以把数组所有元素统一转成小写,再用$in匹配小写的目标值,同样能实现大小写不敏感效果:
db.items.aggregate([ { $match: { $expr: { $in: [ "item1", { $map: { input: { $ifNull: ["$order.products.item", []] }, as: "item", in: { $toLower: "$$item" } } } ] } } } ])
验证结果
运行上述替代Query3的代码,会正确返回2条预期数据:
{ "_id" : ObjectId("6536c0e6cbf03c71e4b2dbee"), "order" : { "order_id" : 1, "products" : [ { "item" : "item1" }, { "item" : "item2" } ] } } { "_id" : ObjectId("6536c0e6cbf03c71e4b2dbef"), "order" : { "order_id" : 2, "products" : [ { "item" : "Item1" }, { "item" : "item2" } ] } }
内容的提问来源于stack exchange,提问作者David Wood
相关产品推荐
相关产品推荐

