首页 > 解决方案 > 使用 Mongoose ArrayFilters 更新嵌套子文档时出错

问题描述

我有一个想要更新嵌套子文档的 Mongoose 集合。

基本设置是这样的:


我希望能够找到一个孙子并更新它。我的方法是找到包含孙子的父(地图),然后更新它。

这些是我的简化模式:

const phaseSchema = new mongoose.Schema(
  {
    name: String,
    color: String,
    steps: [
      new mongoose.Schema(
        {
          name: String,
          body: String,
          entry: {
            type: mongoose.SchemaTypes.ObjectId,
            ref: 'entry',
            default: null
          }
        },
        { timestamps: false }
      )
    ]
  },
  { timestamps: false, _id: true }
)

const mapSchema = new mongoose.Schema(
  {
    name: String,
    phases: [phaseSchema]
  },
  { timestamps: false }
)

export const Map = mongoose.model('map', mapSchema)

我正在尝试使用 ArrayFilters 来查找和更新子文档,但没有运气:

req.body = {
    map_id: 'some_mongoose_id',
    step_id: 'some_other_mongoose_id'
}
const newEntryId = 'a_new_mongoose_id'

// Find the parent (Map) and update it
const UpdatedMap = await Map.update(
    { _id: req.body.map_id }, 
    {
        $set: {
          'phases.$[i].steps.$[j].entry': mongoose.Types.ObjectId(newEntryId)
        }
    },
    {
        arrayFilters: [
            {
                'i.steps._id': mongoose.Types.ObjectId(req.body.step_id)
            },
            {
                'j._id:': mongoose.Types.ObjectId(req.body.step_id)
            }
        ]
    }
)

这会引发以下错误:

错误:在架构中找不到路径“phases.0.steps.0._id:”

巧合的是,我尝试更新的阶段和步骤都在索引 0 处。

如果我换出 arrayFilters 并对索引进行硬编码,就像这样$set: {'phases.0.steps.0.entry': mongoose.Types.ObjectId(newEntryId)'},它可以工作。

我究竟做错了什么?

标签: javascriptnode.jsmongodbexpressmongoose

解决方案


i是导致错误的原因,它也是多余的。没有它,嵌套的 arrayFilter 将根据需要工作。

const UpdatedMap = await Map.update(
    { _id: req.body.map_id }, 
    {
        $set: {
          'phases.steps.$[j].entry': mongoose.Types.ObjectId(newEntryId)
        }
    },
    {
        arrayFilters: [
            {
                'j._id:': mongoose.Types.ObjectId(req.body.step_id)
            }
        ]
    }
)


推荐阅读