【问题标题】:Incorrect Subdocument Being Updated?不正确的子文档正在更新?
【发布时间】:2013-09-30 15:03:32
【问题描述】:

我有一个包含一组子文档的架构,我只需要更新其中一个。我使用子文档的 ID 执行findOne,然后在返回的数组中的位置 0 处减少对该子文档的响应。

无论我做什么,我只能更新父文档中的第一个子文档,即使它应该是第二个、第三个等。无论如何,只有第一个被更新。据我所知,它应该可以工作,但我不是 MongoDB 或 Mongoose 专家,所以我显然在某个地方错了。

 var template = req.params.template;
  var page = req.params.page;
  console.log('Template ID: ' + template);

  db.Template.findOne({'pages._id': page}, {'pages.$': 1}, function (err, tmpl) {
    console.log('Matched Template ID: ' + tmpl._id);
    var pagePath = tmpl.pages[0].body;
    if(req.body.file) {
      tmpl.pages[0].background = req.body.filename;
      tmpl.save(function (err, updTmpl) {
        console.log(updTmpl);
        if (err) console.log(err);
      });
      // db.Template.findOne(tmpl._id, function (err, tpl) {
      //   console.log('Additional Matched ID: ' + tmpl._id);
      //   console.log(tpl);
      //   tpl.pages[tmpl.pages[0].number].background = req.body.filename;
      //   tpl.save(function (err, updTmpl){
      //     if (err) console.log(err);
      //   });
      // });
    }

在控制台中,所有 ID 都正确匹配,即使当我返回 updTmpl 时,它也表示它更新了正确的记录,即使它实际上更新了第一个子文档而不是它所说的那个。

架构以防万一:

var envelopeSchema = new Schema({
  background: String,
  body: String
});

var pageSchema = new Schema({
  background: String,
  number: Number,
  body: String
});

var templateSchema = new Schema({
  name: { type: String, required: true, unique: true },
  envelope: [envelopeSchema],
  pagecount: Number,
  pages: [pageSchema]
});
templateSchema.plugin(timestamps);

module.exports = mongoose.model("Template", templateSchema);

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    Mongoose 不理解使用位置投影运算符返回的文档。它总是按位置 更新子文档数组,而不是按 id。您可能有兴趣查看 mongoose 正在构建的实际查询 - 使用 mongoose.set('debug', true)

    您必须要么获取整个数组,要么构建自己的 MongoDB 查询并绕过 mongoose。我建议前者;如果拉动整个数组会导致性能问题,那么最好将每个子文档都设为顶级文档 - 无限制增长的文档会成为问题(至少因为 Mongo 有硬文档大小限制) .

    【讨论】:

      【解决方案2】:

      我不熟悉 mongoose,但 Mongo 更新查询可能是:

      db.Template.update( { "pages._id": page }, { $set: { "pages.$.body" : body } } )
      

      【讨论】:

        【解决方案3】:

        首先,如果您需要设置 req.body.file 以执行更新,我建议您在运行查询之前进行检查。

        另外,这是一个错字和 req.body.file 应该是 req.body.filename 吗?我假设它是用于示例的。

        此外,我还没有对此进行认真的测试,但我相信如果您指定您的 Template._id,您的调用会更有效率:

        var template_id = req.params.template,
            page_id = req.params.page;
        
        if(req.body.filename){
        
            db.Template.update({_id: template_id, 'pages._id': page_id},
                { $set: {'pages.$.background': req.body.filename} },
                function(err, res){
                    if(err){
                        // err
                    } else {
                        // success
                    }
                });
        } else {
            // return error / missing data
        }
        

        【讨论】:

        • 是的,req.body.file 是通过文件上传中间件设置的,超出了此处提供的代码范围。所以这不是一个错字。 :) 您的更新代码有效,我仍然需要编写一些额外的东西来获取我设置的 pagePath,因为它在此方法中需要进一步,但更新解决了我在使用位置投影运算符时遇到的问题。谢谢。
        猜你喜欢
        • 1970-01-01
        • 2023-03-04
        • 2014-12-19
        • 1970-01-01
        • 1970-01-01
        • 2019-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多