2017-09-24 130 views
0

我有一个API调用需要更新两个单独集合的场景。如果一次更新失败,我需要恢复第一次更新。我如何确保两项操作都能成功完成,否则无法完成。为了澄清,这里是情况。在express框架中使用MongoJS。MongoDB多个集合更新

问题型号

{ 
    _id: ObjectId(), 
    title: String, 
    description: String, 
    accepted: String, 
    // Some other fields 
} 

应答模型

{ 
    _id: ObjectId(), 
    qid: String, //ObjectId of question its linked to 
    body: String, 
    accepted: boolean, 
    // Some other fields 
} 

方法1: 首先要将对应于请求中的id答案。将其标记为已接受并获得qid。将answer id插入对应于qid的问题文档中。如果第二次操作失败,则恢复第一次操作。但是,如果数据库连接丢失,则无法执行。

方法2 首先得到相应的问题qid。用answer id更新accepted字段,然后获取与其对应的答案并将其标记为已接受。

然后有这样的情况,如果一个答案被接受,我们需要使所有其他答案不被接受。这是一个第三个操作。此外,它是一种切换操作,所以如果它已被接受,我们需要做相反的事情。

我有一种感觉,有一种更清洁和更安全的方式来处理这种情况。

回答

0

MongoDB does not have a way of doing multi-document transactions。所以没有像这样做回滚的干净方式。它必须在应用程序中执行。 MongoDB文档建议使用two-phase commit模式来创建类似事务的语义。你可以使用这个来实现回滚,但这可能非常麻烦。

另一种方法是重新考虑文档模式。你可以在你的question文件中嵌入你的answer文件吗?使用嵌入式文档将更好地利用Mongo的功能,而不是试图执行事务。 MongoDB对单个文档进行原子写入,因此如果在更新嵌入式文档时出现错误,则可以回滚整个操作。

+0

嵌入将有问题。这将是一系列答案,随后将会有一系列答复。然后执行回复更新将变得不可能。 – Nil

+0

嗯......你想要在答案和问题的同时更新答复和答案/问题吗?如果没有,可能在一个单独的集合中有回复,并且在答案中只有一个'_id'的回复可能有效? – tfogo