如何转换MongoDB嵌套对象数组中的日期字符串并查询当月文档
问题原因
- 嵌套数组路径访问错误:
sections和fields都是数组结构,不能直接使用$sections.field[0].value这类路径访问嵌套值,且不能假设name=Date的字段固定在数组首位,必须按字段名匹配取值。 - 条件判断逻辑错误:
$sections.field.value返回的是所有字段value组成的数组,直接与字符串Date判等永远不成立,无法正确识别日期字段。
正确实现方案
首先提取嵌套数组中name=Date对应的值,转换为日期类型后再做月份范围匹配,完整实现代码如下:
const startOfMonth = moment(payload.forPeriod).startOf("month").toDate(); const endOfMonth = moment(payload.forPeriod).endOf("month").toDate(); const existingReports = await Report.aggregate([ // 提取日期字段并转换为日期类型 { $addFields: { documentDate: { $reduce: { input: "$sections", initialValue: null, in: { $cond: { if: { $ne: ["$$value", null] }, then: "$$value", else: { $let: { vars: { // 过滤出name为Date的字段 dateField: { $arrayElemAt: [ { $filter: { input: "$$this.fields", cond: { $eq: ["$$this.name", "Date"] } } }, 0 ] } }, in: { $cond: { if: { $ne: ["$$dateField", null] }, // 日期字符串转日期类型 then: { $dateFromString: { dateString: "$$dateField.value" } }, else: null } } } } } } } } } }, // 匹配指定月份范围内的文档 { $match: { documentDate: { $gte: startOfMonth, $lt: endOfMonth } } } ])
如果确认每个文档的sections数组只有1个元素,且name=Date的字段固定在fields数组首位,可以使用简化写法:
const existingReports = await Report.aggregate([ { $addFields: { documentDate: { $dateFromString: { dateString: "$sections.0.fields.0.value" } } } }, { $match: { documentDate: { $gte: moment(payload.forPeriod).startOf("month").toDate(), $lt: moment(payload.forPeriod).endOf("month").toDate() } } } ])
内容的提问来源于stack exchange,提问作者Thomas。
相关产品推荐
相关产品推荐

