新日期不能与 $match 聚合一起正常工作?

问题描述 投票:0回答:1

我正在尝试通过开始使用

$unwind
来破坏日期数组来过滤一些日期数据:

"startDates": [
     "2024-05-15T09:30:00.000Z",
     "2024-11-13T10:00:00.000Z",
     "2024-02-10T00:00:00.000Z"
 ] 

使用:

{
  $unwind: "$startDates",
},

然后使用

$match
过滤年份数据:

{
  $match: {
    startDates: {
      $gte: new Date(`${year}-01-01`),
      $lte: new Date(`${year}-12-31`),
    },
  },
},

但是响应返回一个空数组

{
  "status": "Success",
  "result": 0,
  "data": {
    "plan": []
  }
}

但是当我删除

new Date
并手动写入日期时,响应返回我想要的数据 像这样:

{
  $match: {
    startDates: {
      $gte: `${year}-01-01`,
      $lte: `${year}-12-31`,
    },
  },
},

但是当我尝试使用

$group
对数据进行分组并使用
$month
pupline 时,它会向我显示以下错误:

{
  "status": "failed",
  "message": "PlanExecutor error during aggregation :: caused by :: can't convert from BSON type string to Date"
}

这是完整的功能代码:

exports.getMonthlyPlan = async (req, res) => {
  try {
    const year = req.params.year * 1;
    const plan = await Tour.aggregate([{
        $unwind: "$startDates",
      },
      {
        $match: {
          startDates: {
            $gte: `${year}-01-01`,
            $lte: `${year}-12-31`,
          },
        },
      },
      {
        $group: {
          _id: {
            $month: "$startDates"
          },
          numTourStarts: {
            $sum: 1
          },
        },
      },
    ]);

    res.status(200).json({
      status: "Success",
      result: plan.length,
      data: {
        plan,
      },
    });
  } catch (error) {
    res.status(400).json({
      status: "failed",
      message: error.message,
    });
  }
};

我希望我已经清楚地解释了这些问题

我正在尝试使用

new Date
功能,但我不明白这个问题

javascript node.js mongodb datetime aggregate
1个回答
0
投票

将日期值存储为字符串是一个设计缺陷,您不应该永远这样做。始终存储正确的

Date
物品。

首先,您可以通过如下更新来转换数据类型:

db.collection.updateMany(
   { startDates: { $type: "string" } },
   [
      {
         $set: {
            startDates: {
               $map: {
                  input: "$startDates",
                  in: { $dateFromString: { dateString: "$$this" } }
               }
            }
         }
      }
   ]
)

然后你的查询就会起作用。这个可能会提供更好的性能:

db.gcollection.aggregate([
   {
      $match: {
         startDates: {
            $gte: new Date(`${year}-01-01`),
            $lte: new Date(`${year}-12-31`)
         }
      }
   },
   {
      $set: {
         startDates: {
            $filter: {
               input: "$startDates",
               cond: { $eq: [{ $year: "$$this" }, year] }
            }
         }
      }
   },
   { $unwind: "$startDates" },
   {
      $group: {
         _id: { $month: "$startDates" },
         numTourStarts: { $count: {} }
      }
   }
])
© www.soinside.com 2019 - 2024. All rights reserved.