Comment on page

通过findAndModify进行线性化读取

概述

从复制集读取数据时,可能会读取过时(即可能并不能反映所有写道,发生前读操作)或不持久(即数据可能反映了写的状态还没有得到多数或复制集成员因此可以回滚)的数据,这取决于所使用的读取关注点。
本教程概述了一个替代过程,对于使用MongoDB 3.2的部署,该过程使用db.collection.findAndModify()来读取不过时且不能回滚的数据。对于MongoDB 3.4,尽管可以应用概述的过程,但请参阅[“线性化”]([https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern.%22linearizable%22](https://docs.mongodb.com/manual/reference/read-concern-linearizable/#readconcern."linearizable"))阅读问题。

可线性通过findAndModify读取

此过程用于db.collection.findAndModify()读取不过期且无法回滚的数据。为此,该过程使用findAndModify()具有写关注的方法来修改文档中的伪字段。具体来说,该过程要求:

前提条件

本教程从名为products的集合中读取内容。使用以下操作初始化集合。
db.products.insert( [
{
_id: 1,
sku: "xyz123",
description: "hats",
available: [ { quantity: 25, size: "S" }, { quantity: 50, size: "M" } ],
_dummy_field: 0
},
{
_id: 2,
sku: "abc123",
description: "socks",
available: [ { quantity: 10, size: "L" } ],
_dummy_field: 0
},
{
_id: 3,
sku: "ijk123",
description: "t-shirts",
available: [ { quantity: 30, size: "M" }, { quantity: 5, size: "L" } ],
_dummy_field: 0
}
] )
该集合中的文档包含一个虚拟字段_dummy_field,该字段 db.collection.findAndModify()在本教程中将通过递增 。如果该字段不存在,则该db.collection.findAndModify()操作会将字段添加到文档中。该字段的目的是确保db.collection.findAndModify()对文档进行修改。

程序

1.创建一个唯一索引。

在将用于指定db.collection.findAndModify()操作中完全匹配的字段上创建唯一索引。
本教程将在sku现场使用完全匹配。这样,在sku字段上创建唯一索引。
db.products.createIndex( { sku: 1 }, { unique: true } )

2.使用findAndModify读取提交的数据。

使用该db.collection.findAndModify()方法对要阅读的文档进行简单更新,然后返回修改后的文档。需要写关注。要指定要阅读的文档,必须使用唯一索引支持的完全匹配查询。[{ w: "majority" }](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")
下面的findAndModify()操作在唯一索引的字段sku上指定精确匹配,并增加匹配文档中名为_dummy_field的字段。虽然不是必需的,但该命令的写操作还包括一个5000毫秒的wtimeout值,以防止在写操作不能传播到大多数投票成员时永远阻塞操作。
var updatedDocument = db.products.findAndModify(
{
query: { sku: "abc123" },
update: { $inc: { _dummy_field: 1 } },
new: true,
writeConcern: { w: "majority", wtimeout: 5000 }
}
);
由于仲裁读取过程只会增加文档中的虚拟字段,因此您可以安全地重复调用 findAndModify(),根据需要调整 wtimeout
译者:杨帅
校对:杨帅