MongoDB如何在对象数组中对多类型值执行正则搜索?
MongoDB 正则匹配非字符串类型值的解决方案
问题背景
集合数据结构简化如下:
[ { items: [ { id: '000', value: 'string' }, { id: '001', value: 1234 }, { id: '002', value: true }, ... ] }, { items: [ { id: '000', value: 'another string' }, { id: '001', value: 2345 }, { id: '002', value: false }, ... ] }, ... ]
需求是根据用户选择的id,对对应value执行正则子串匹配。当前使用的聚合$match阶段代码如下:
{ $match: { items: { $elemMatch: { item_id: { $in: ['000', '002'] }, item_data: { $regex: 'e', $options: 'i' } } } } }
实际问题:$regex仅对字符串类型生效,无法匹配true转字符串后的"true"中的'e',导致预期的两个匹配文档只返回一个。需要将非字符串类型的value转为字符串后再执行正则匹配,询问是否可通过$elemMatch实现,或需要其他操作符。
解决方案
$elemMatch本身无法在查询阶段直接转换字段类型,因为$match的查询条件基于原始字段值。需要借助聚合管道的其他阶段处理类型转换,以下是两种可行方案:
方案一:预处理字段后匹配(推荐,易读且性能可控)
先通过$addFields生成一个转换后的数组字段,再基于该字段执行匹配:
[ { $addFields: { processedItems: { $map: { input: "$items", as: "item", in: { id: "$$item.id", valueStr: { $toString: "$$item.value" } } } } } }, { $match: { processedItems: { $elemMatch: { id: { $in: ['000', '002'] }, valueStr: { $regex: 'e', $options: 'i' } } } } }, // 可选:移除临时处理字段,保留原文档结构 { $project: { processedItems: 0 } } ]
$map遍历items数组,将每个元素的value通过$toString转为字符串,生成processedItems临时字段- 在后续
$match阶段,对processedItems使用$elemMatch同时匹配指定id和正则条件 - 最后用
$project移除临时字段,不影响原文档结构
方案二:使用$expr直接在$match中写表达式(无需临时字段,但性能受限)
通过$expr在$match内嵌入表达式,直接处理类型转换和匹配逻辑:
{ $match: { $expr: { $gt: [ { $size: { $filter: { input: "$items", cond: { $and: [ { $in: ["$$this.id", ['000', '002']] }, { $regexMatch: { input: { $toString: "$$this.value" }, regex: 'e', options: 'i' } } ] } } } }, 0 ] } } }
$filter遍历items数组,筛选出符合id在指定列表、且value转字符串后匹配正则的元素$size获取筛选结果的长度,只要长度大于0,说明文档符合匹配条件- 注意:
$expr内的表达式无法利用索引,数据量较大时会影响查询性能,适合小数据集场景
内容的提问来源于stack exchange,提问作者walderich
相关产品推荐
相关产品推荐

