You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB报错:无法将BSON字符串类型转为Date类型求助

问题描述

尝试通过URL参数过滤MongoDB存储的数据时,服务器崩溃并报错:can't convert from BSON type string to Date,已尝试将参数转为Number但问题依旧。

前端请求代码

async filter(){
        month = this.$refs.month.value;
        year = this.$refs.year.value;

        if(month != "Month" && year != ""){
          const addressToFetch = "/api/budget/" + year + "/" + month;
          console.log("Fetching" + addressToFetch);
          await fetch(addressToFetch).then(response => response.json())
      .then(response => {
          this.expenses = response;
          console.log(response);
      });

        }
    }

该函数通过点击HTML表单按钮触发,获取两个输入框的年月值并发送请求。

后端处理代码

app.get("/api/budget/:year/:month", verify, async (req, res) => {
  const user = req.session.user;

  const year = Number(req.params.year);
  const month = Number(req.params.month);

  console.log("Got " + year + "/" + month);

  const expenses = db
    .collection("expenses")
    .find({
      "users.username": user.username,
      $expr: {
        $and: [
          { $eq: [{ $year: "$date" }, year] },
          { $eq: [{ $month: "$date" }, month] },
        ],
      },
    })
    .toArray();

  console.log(expenses);
  res.json(expenses);
});

数据库示例文档

[
    {
        "_id": "6571eb70320499f416931fd8",
        "id": 2,
        "date": "2021-09-06T00:00:00.000Z",
        "description": "boringday",
        "category": "transport",
        "buyer": "giacomo",
        "cost": 49,
        "users": [
            {
                "username": "paolo",
                "amount": 16.333333333333332
            },
            {
                "username": "giacomo",
                "amount": 16.333333333333332
            },
            {
                "username": "giacomo",
                "amount": 16.333333333333332
            }
        ]
    },
    {
        "_id": "6571eb70320499f416931fe8",
        "id": 18,
        "date": "2019-04-10T00:00:00.000Z",
        "description": "badday",
        "category": "school",
        "buyer": "giacomo",
        "cost": 329,
        "users": [
            {
                "username": "luca",
                "amount": 109.66666666666667
            },
            {
                "username": "luca",
                "amount": 109.66666666666667
            },
            {
                "username": "giacomo",
                "amount": 109.66666666666667
            }
        ]
    },
    {
        "_id": "6571eb70320499f416931feb",
        "id": 21,
        "date": "2021-11-14T00:00:00.000Z",
        "description": "boringexperience",
        "category": "school",
        "buyer": "giacomo",
        "cost": 299,
        "users": [
            {
                "username": "giorgia",
                "amount": 99.66666666666667
            },
            {
                "username": "giacomo",
                "amount": 99.66666666666667
            },
            {
                "username": "giacomo",
                "amount": 99.66666666666667
            }
        ]
    },
    {
        "_id": "6571eb70320499f416931fff",
        "id": 41,
        "date": "2020-04-09T00:00:00.000Z",
        "description": "badtool",
        "category": "sport",
        "buyer": "giacomo",
        "cost": 349,
        "users": [
            {
                "username": "franco",
                "amount": 116.33333333333333
            },
            {
                "username": "franco",
                "amount": 116.33333333333333
            },
            {
                "username": "giacomo",
                "amount": 116.33333333333333
            }
        ]
    }
]

期望:当提交year=2021, month=11时,仅返回第三个文档。


解决方案

报错核心原因:数据库中date字段存储的是字符串类型,但MongoDB的$year、$month操作符仅支持Date类型数据。提供两种解决思路:

思路1:查询时动态转换字符串为Date

修改后端查询逻辑,用$dateFromString将字符串日期转为Date类型后再提取年月,同时修复异步操作未加await的问题:

app.get("/api/budget/:year/:month", verify, async (req, res) => {
  const user = req.session.user;

  const year = Number(req.params.year);
  const month = Number(req.params.month);

  console.log("Got " + year + "/" + month);

  try {
    const expenses = await db
      .collection("expenses")
      .find({
        "users.username": user.username,
        $expr: {
          $and: [
            { $eq: [{ $year: { $dateFromString: { dateString: "$date" } } }, year] },
            { $eq: [{ $month: { $dateFromString: { dateString: "$date" } } }, month] },
          ],
        },
      })
      .toArray();

    console.log(expenses);
    res.json(expenses);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: "Server error" });
  }
});

思路2:批量修改数据库字段类型(推荐)

如果允许修改数据库,将所有date字段从字符串转为Date类型,后续查询更高效:

// 在MongoDB Shell或MongoDB Compass中执行此命令
db.expenses.updateMany(
  { date: { $type: "string" } },
  [
    { $set: { date: { $dateFromString: { dateString: "$date" } } } }
  ]
)

转换完成后,原后端查询逻辑即可正常工作。

前端代码优化(可选)

补充变量声明避免全局污染,同时优化异步代码写法:

async filter(){
    const month = this.$refs.month.value;
    const year = this.$refs.year.value;

    if(month != "Month" && year != ""){
      const addressToFetch = "/api/budget/" + year + "/" + month;
      console.log("Fetching" + addressToFetch);
      try {
        const response = await fetch(addressToFetch);
        const data = await response.json();
        this.expenses = data;
        console.log(data);
      } catch (err) {
        console.error("请求失败:", err);
      }
    }
}

内容的提问来源于stack exchange,提问作者Eminent Emperor Penguin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:25:00