【问题标题】:Mongoose query with await returns undefined带有 await 的 Mongoose 查询返回未定义
【发布时间】:2021-07-03 23:24:34
【问题描述】:

以下代码在快速路由处理程序中循环编写;

const projects = await Projects.find({});//working fine
for (let i = 0; i < projects.length; i++) {
    const project = projects[i];
    const build = await Build.find({ id: project.latest_build});
    //logger.debug(build[0].status); //error
    const features = await Feature.find({ build_id: project.latest_build});
    logger.debug(features[0].status);

}

上面的代码在第 4 行给出了错误。

(node:672375) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'status' of undefined

但是,它已正确打印在日志中。似乎变量的值被一个承诺懒惰地填充。

但是第 6 行总是可以正常工作。

注意:我没有对上述集合执行任何其他读/写操作。

更新

  • idBuild 集合的唯一键。
  • build_idFeature 集合的普通字段。

架构和文档是这样创建的


Schemas.Projects =  new mongoose.Schema({
    id: {
        type: String,
        unique: true
    },
    title: String,
    latest_build: String
});
Schemas.Build =  new mongoose.Schema({
    id: {
        type: String,
        unique: true
    },
    run_date: Date,
    status: String,
});

Schemas.Feature =  new mongoose.Schema({
    id : String,
    build_id: String,
    summary : String,
    status: String,
    flows: Number,
});

const Projects = mongoose.model('Projects', Schemas.Projects);
const Build = mongoose.model(`Build_${projId}`, Schemas.Build);
const Feature = mongoose.model(`Feature_${projId}`, Schemas.Feature);

【问题讨论】:

  • > 似乎变量的值被一个承诺懒惰地填充。 - 不,这不对。您可以尝试直接在 mongo 中执行相同的查询吗?构建模型是如何定义的?
  • 在 mongo 中工作正常。 idBuild 模型中的唯一键。我已经更新了同样的问题。
  • 第 2 行记录了正确的值,然后仍然抛出错误?
  • @raina77ow 我已经用Build 模式更新了这个问题。这是你要的吗? logger.debug(build) 打印 [ { _id: 60e048a6d62e4f2c71363796, id: '1', run_date: 2021-07-03T11:23:18.934Z, status: 'passed', __v: 0 } ]
  • @TusharShahi 是的。即使此代码正确记录但给出错误Build.find({ id: project.latest_build}, (err,docs) =&gt; { logger.debug(docs[0].status); });

标签: node.js mongoose async-await


【解决方案1】:

有问题的代码的问题在于它的期望过于乐观。这一行……​​

const build = await Build.find({ id: project.latest_build });
logger.debug(build[0].status)

...假设查询总是找到至少一个构建文档。但是,由于代码作为循环的一部分运行,结果实际上是混合的:

  • 在第一次迭代中,查询确实通过第一个项目的数据找到了 Build 对象,并正确记录了其状态
  • 在第二次迭代中,它改为返回一个空数组。然后代码在尝试访问build[0]status 属性时抛出错误(未定义)。

此问题的适当解决方案取决于您应如何处理这些情况。如果每个项目必须有一个对应的 Build(这是一个严格的 1-1 关系),那么向您抛出一个错误实际上很好,因为您只需要修复它。

不过,可能值得将其视为“已知错误”,如下所示:

const buildId = project.latest_build;
const builds = await Build.find({ id: buildId });
if (!builds.length) {
  logger.error(`No build found for ${buildId}`);
  continue;
}

在这种情况下(假设记录器设置正确),您的代码不会崩溃,但会记录错误。但是,如果实际上还没有构建是正常的情况,只需删除日志记录 - 并将这种情况视为 已知 边缘情况。

【讨论】:

    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 2020-04-02
    • 2020-08-24
    • 2020-07-11
    • 2020-07-15
    • 2021-10-21
    • 1970-01-01
    • 2017-12-14
    相关资源
    最近更新 更多