- MongoDB CRUD 操作 >
- MongoDB CRUD 教程 >
- 隔离操作的序列
隔离操作的序列¶
概述¶
在单文档级别上写操作是原子的:没有单个的写操作可以原子地影响不止一个文档或者集合。
当一个单独的写操作修改多个文档的时候,这一整个操作不是原子的,并且其他操作可能交错。一个单文档或者记录的修改总是原子的,即使写操作修改多个子文档 内 的单个记录。
没有其他的操作是原子的;然而,你可以使用 isolation operator 来 隔离 一个影响多个文档的写操作。
这个文档描述了一种方法, 仅仅 当本地文档副本反映数据库中文档的当前状态时更新文档。另外,下面的方法提供了一个管理隔离操作序列的途径:
- the findAndModify() provides an isolated update and return operation.
- 执行两个阶段的提交
创建一个 unique index ,以保证当你插入的时候这个键不存在。
Update if Current¶
在这个模型下,你将:
查询一个文档,
修改在那个文档中的字段
并且 仅仅当 集合中的字段自查询以来没有发生变化的时候更新这些字段。
思考下面的JavaScript例子,它尝试更新 products 集合里面的一个文档的 qty 字段:
在 2.6 版更改: 现在 db.collection.update() 方法返回一个包含操作状态的 WriteResult() 对象。以前的版本需要一个额外的 db.getLastErrorObj() 方法调用。
var myCollection = db.products;
var myDocument = myCollection.findOne( { sku: 'abc123' } );
if (myDocument) {
var oldQty = myDocument.qty;
if (myDocument.qty < 10) {
myDocument.qty *= 4;
} else if ( myDocument.qty < 20 ) {
myDocument.qty *= 3;
} else {
myDocument.qty *= 2;
}
var results = myCollection.update(
{
_id: myDocument._id,
qty: oldQty
},
{
$set: { qty: myDocument.qty }
}
);
if ( results.hasWriteError() ) {
print("unexpected error updating document: " + tojson( results ));
} else if ( results.nMatched == 0 ) {
print("No update: no matching document for { _id: " + myDocument._id + ", qty: " + oldQty + " }")
}
}
你的应用可能需要对这个模型进行一些修改,比如:
在 update() 操作里使用整个文档作为查询条件,以使这个操作更加通用( generalize the operation)并且保证原始的文档未被修改,而不仅仅是保证单个字段未改变。
为这个文档添加一个版本变量,that applications increment upon each update operation to the documents. 在查询表达式中使用这个版本变量。你必须能够保证 所有 连接到你的数据库的客户端遵从这个约束。
在更新表达式中使用 $set 来仅仅修改你的(要修改的)字段,并且预防覆盖其他字段。
使用 创建一个自增的序列字段 中描述的方法中的一个。