【问题标题】:$matching with field added with $dateToString doesn't work$matching 与 $dateToString 添加的字段不起作用
【发布时间】:2021-05-10 06:35:55
【问题描述】:

在我的 MongoDB 集合中,我有包含嵌套字符串字段的文档,其中包含月份和年份,例如'04/2021'。示例文档:

{
    "_id": {
        "$oid": "608ba45cec43c5b24cda034b"
    },
    "status": "pass",
    "stage": 5,
    "priority": 0,
    "payload": {
        "company_id": "8800",
        "company_name": "<MY COMPANY>",
        "target_period": "04/2021"
    },
    "retry_count": 0,
    "build_number": "101",
    "job_name": "P123",
    "createdAt": {
        "$date": "2021-04-30T06:31:56.000Z"
    },
    "updatedAt": {
        "$date": "2021-05-10T03:55:44.686Z"
    }
}

我正在尝试编写一个聚合管道,该管道将动态返回所述字段指向过去一个月的文档。例如,本月(2021 年 5 月)运行,我会收到标有“04/2021”的文档。从this post,我找到了用于获取比较字符串的oneliner:new Date(new Date().getFullYear(), new Date().getMonth(), 1)。 (我知道,由于getMonth 返回一个从零开始的月份索引,所以上个月的工作是偶然的,必须以某种方式解决。)

此管道不起作用:

[
    {
        $addFields: {
            previous_month: {
                $dateToString: {
                    'date': new Date(new Date().getFullYear(), new Date().getMonth(), 1),
                    'format': '%m/%G'
                }
            }
        }
    },
    {
        $match: {
            "payload.target_period": "$previous_month"
        }
    }
]

使用 MongoDB Compass,我可以看到 previous_month 字段被 $addFields 阶段填充得很好(上面的示例文档获得值 04/2021),但 $match 阶段返回 0 个文档。我正在运行 MongoDB 版本 4.2.12。

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    您应该使用$expr 运算符,同时尝试在内部文档中自我引用另一个 ket $match舞台。

    [
      {
        $addFields: {
          previous_month: {
            $dateToString: {
              'date': new Date(new Date().getFullYear(), new Date().getMonth(), 1),
              'format': '%m/%G'
            }
          }
        }
      },
      {
        $match: {
          $expr: {
            $eq: [ "$payload.target_period",  "$previous_month" ],
          },
        }
      }
    ]
    

    【讨论】:

    • 这行得通,$eq 周围没有额外的大括号。
    • 对不起。感谢您指出。更新了我的答案
    【解决方案2】:

    我认为您可以使用客户端语言(js,nodejs)轻松准备输入日期,而不是在查询中进行整个过程,

    • 准备了一个函数zeroFill,如果小于10,它将返回带有concat 0的数字,
    • 获取上个月日期并选择上个月
    • 结合月份和年份

    function zeroFill(i) { return (i < 10 ? '0' : '') + i; }
    
    var date = new Date();
    date.setMonth(date.getMonth() - 1);
    let searchDate = zeroFill(date.getMonth() + 1) + "/" + date.getFullYear();
    
    console.log(searchDate); // mm/yyyy
    • 您的查询将是:
    [{ $match: { "payload.target_period": searchDate } }]
    

    Playground

    【讨论】:

      【解决方案3】:

      我建议moment.js 库,使用起来要简单得多:

      { $match: { "payload.target_period": moment().startOf("months").subtract(1, "months").format("MM/YYYY") } }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多