MongoDB交易&索引

时间:2012-08-09 17:15:49

标签: mongodb

我对MongoDB相对较新,并且正在实施受此技术启发的交易:

http://cookbook.mongodb.org/patterns/perform-two-phase-commits/

我正在考虑如何阻止给定源/目标帐户的同时交易。例如,我可以通过声明源唯一索引来阻止同一源上的同时事务:

transactionsCollection.ensureIndex({"source":1}, {unique: true});
var newDoc = {source: sourceID, destination: destinationID, 
              amount: 100, state:"pending"}
transactionsCollection.save(newDoc, {safe:true}, function(error, t) {
    if (error.name == "MongoError" && error.code == 11001)
        // duplicate index, so I'm locked out
}

但是,如果源或目标已经在事务表中(作为源或目标),我真正想要的是被锁定。

所以我的问题是,是否可以以允许上述方式设置索引,或者如果没有其他方式来实现这一点。

谢谢!

2 个答案:

答案 0 :(得分:2)

在记录中使用数组(下面为tags)的唯一索引应该可以完成这个技巧。例如:

db.test.save({ name: 'one', tags: [1, 2] });
db.test.save({ name: 'two', tags: [3, 4] });
db.test.ensureIndex({ tags: 1 }, {unique: 1});

db.test.save({ name: 'three', tags: [4, 5] });
E11000 duplicate key error index: test.test.$tags_1  dup key: { : 4 }

答案 1 :(得分:0)

要实际放置一个实际回答问题的答案,您将在评论中看到我建议在子文档上放置一个唯一索引,以便文档看起来像:

{
    _id:{},
    accounts: [1,2],
    source: 1,
    destination: 2
}

在帐户字段上放置一个唯一索引会对任何挂起的交易产生一个帐户1和2的锁定,以便在完成之前停止进一步的交易。所以这意味着如果存在待处理的交易,那么它将拯救源或目的地是1还是2。

但是,在某些情况下你无法承担子文档的顺序,因为对于像这样的完整事务,我不会使用子文档来判断事务的方向,如:

dest_source: [1,2]

表示帐户1正在支付帐户2,因为此索引的顺序可能会随着您保存的方式而改变,因此我将仅使用子文档创建索引类型,该索引类型在使用{时考虑索引中的排列{1}}和source字段实际了解交易的移动方向,因为即使文档更改顺序,您仍然可以通过命名字段了解方向。

我相信这就是OP真正想要的。