MongoDB:确保引用的文档仍然存在

时间:2012-01-20 01:02:56

标签: mongodb mongoose

假设我有两种类型的MongoDB文档:“项目”和“任务”。项目可以有很多任务。在我的情况下,更适合链接文档而不是嵌入。

当用户想要保存任务时,我首先验证正在分配任务的项目是否存在,如下所示:

// Create new task
var task = new Task(data);
// Make sure project exists
Project.findById(task.project, function(err, project) {
  if(project) {
    // If project exists, save task
    task.save(function(err){
      ...    
    });
  } else {
    // Project not found
  }
});

我担心的是,如果另一个用户在运行Project.findById()查询后删除了项目,但在保存任务之前,无论如何都会创建任务,而不会引用项目。

这是一个有效的问题吗?有没有什么做法可以防止这种情况发生,或者这只是MongoDB必须要面对的事情?

2 个答案:

答案 0 :(得分:0)

技术上是的,这是使用MongoDB时需要面对的问题。但这并不是什么大问题,因为很少有人删除项目而另一个人不知道它并为该项目创建任务。我不会使用if语句来检查项目状态,而只是将任务创建为坏记录。您可以手动删除这些错误记录,也可以安排cron任务来清理它们。

答案 1 :(得分:0)

你似乎在做这件事的方式,即两个独立的模型 - 不是子文档(没有看到模型很难分辨),我想你会有这种竞争条件。 if无济于事。你需要利用原子修饰符来避免这个问题,并使用单独的模型(每个模型都是它自己的MongoDB集合),atomic modifiers are not available。在SQL世界中,您将使用事务来确保一致性。类似地,对于像MongoDB这样的文档存储,您可以将每个Task作为Project的子文档,然后只需.push()个新任务。但也许您的用例需要单独的,不相关的模型。 MongoDB非常适合提供这种灵活性,但它使您能够在不使用SQL的情况下保留SQL思维,这可能会导致设计问题。

更重要的是,你担心的竞争条件似乎不是什么大问题。毕竟,也可以在保存任务后删除项目。你显然有一种清理方法。另外一个清理功能不是世界末日 - 无论如何都可能是你的后袋里的好东西。