Mongoose无法删除嵌套文档。

7
我一如既往地陷入了困境,似乎在node项目中经常会遇到这种情况。我不确定是我做错了什么还是遇到了一个bug。
我的Server架构可以有任意数量的嵌套文档称为services。然而,我遇到了一个问题,即使我已经成功地从server对象中删除了单个服务,当我告诉它保存时,它并没有从数据库中删除。保存函数正常工作,因为它保存了我所做的所有更改,并推入新的嵌入式文档,只是没有移除已经存在的文档。
这里是我的代码的一个相对简化的示例:
app.put('/server/:id', function(req, res, next){
  app.Server.findOne({_id: req.params.id}, function(err, server) {
    server.updated = new Date();
    ...

    for (var num = _.size(req.body.server.services) - 1; num >= 0; num--){
      // Is this a new service or an existing one
      if (server.services[num]) {
        // Is it marked for deletion? If so, delete it
        if (req.body.server.services[num].delete == "true") {
          server.services[num].remove()
        } else { // else, update it
          server.services[num].type = req.body.server.services[num].type
          ...
        }
      } else {
        // It's new, add it
        delete req.body.server.services[num]["delete"]
        server.services.push(req.body.server.services[num]);
      }
    }

    server.save(function(err){
      if (!err) {
        req.flash('success', 'Server updated')
      } else {
        req.flash('error', 'Err, Something broke when we tried to save your server. Sorry!')
        console.log(err)
      }
      res.redirect('/')
    });
  })
});

因此,remove() 实际上是在删除服务。如果我在保存之前执行 server.toObject(),它就不会在那里了。有什么想法为什么在保存时它不会从数据库中删除?

编辑:我想版本号可能会有所帮助。 node@0.4.2,mongoose@1.1.5 express@2.0.0rc

2个回答

5
我可能说错了,因为我没有测试过你的示例,但这听起来像是Mongoose没有检测到嵌入式文档已被修改。
模式类型文档页面中可以看到:
由于它是一个无模式类型,您可以将其值更改为任何其他内容,但Mongoose将失去自动检测/保存这些更改的能力。要“告诉” Mongoose Mixed 类型的值已更改,请调用文档的.markModified(path)方法,并传递刚刚更改的Mixed类型的路径。
person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved

因此,你的答案可能就像使用markModified()函数一样简单。

1
这个本来很完美,但是markModified在子元素上不起作用。请参考:https://github.com/LearnBoost/mongoose/issues/435 - k00k
在我的情况下起作用了。非常感谢! - JMax
Carlosedp的解决方案只在少数情况下适用于我。这个方法似乎在任何情况下都有效,并且似乎是更“正确”的方法。谢谢! - Ted Avery

3
我找到了一种临时解决这个问题的方法。
我的做法是将嵌入的文档加载到一个数组中,删掉需要删除的那个,然后替换整个数组。代码大概是这样的:
var oldusers = dl.users;
oldusers.splice(dl.users.indexOf(req.currentUser.id), 1);
dl.users = oldusers;
dl.save(function(err) {...

我知道根据文档的大小,它会


这个确实可以用,但是有没有人知道为什么我们必须使用这个解决方法? - Troy Watt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接