在嵌套数组中使用$dateToString格式化日期的MongoDB聚合查询问题
解决方案:嵌套$map处理多层级日期字段
当然可以在$map里嵌套另一个$map!你之前的问题是把$map.in设成了数组,导致evse对象和处理后的connectors数组被拆成了两个元素,破坏了原有的文档结构。正确的思路是:在处理每个evse对象时,同时更新它自身的last_updated和内部的connectors数组——也就是在$mergeObjects中嵌套处理connectors的逻辑。
以下是修正后的聚合查询,完美保留原文档结构,同时处理所有三层的last_updated字段:
db.collection.aggregate([ { $addFields: { // 转换顶层的last_updated为字符串格式 last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$last_updated' } }, // 处理evses数组,先判断数组是否存在避免报错 evses: { $cond: { if: { $ne: ['$evses', null] }, then: { $map: { input: '$evses', as: 'evse', in: { $mergeObjects: [ '$$evse', // 保留evse原有的所有字段 { // 转换当前evse的last_updated last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$$evse.last_updated' } }, // 嵌套$map处理connectors数组,同样先判断是否存在 connectors: { $cond: { if: { $ne: ['$$evse.connectors', null] }, then: { $map: { input: '$$evse.connectors', as: 'connector', in: { $mergeObjects: [ '$$connector', // 保留connector原有字段 { // 转换当前connector的last_updated last_updated: { $dateToString: { format: '%Y-%m-%dT%H:%M:%SZ', date: '$$connector.last_updated' } } } ] } } }, else: null // 若connectors不存在,保持原状态 } } } ] } } }, else: null // 若evses不存在,保持原状态 } } } } ])
关键细节说明:
- $cond判断字段存在性:因为部分文档可能没有evses或connectors字段,用$cond可以避免$map处理null值时抛出错误,保证查询兼容性。
- 嵌套$map的位置:在处理evse的$mergeObjects中,直接覆盖原有的connectors字段——通过嵌套$map把每个connector的last_updated转换为字符串,同时保留其他字段。
- 结构完全保留:整个查询只会修改所有层级的last_updated字段格式,原文档的嵌套结构、其他字段都不会被改变。
运行这个查询后,你会得到和原文档结构一致的结果,所有last_updated都变成了%Y-%m-%dT%H:%M:%SZ格式的字符串,毫秒部分被移除。
内容的提问来源于stack exchange,提问作者Greggo
相关产品推荐
相关产品推荐

