以下の形式のドキュメントがいくつかあります
{
"count_used" : Int64,
"last_used" : Date,
"enabled" : Boolean,
"data" : String
}
last_used
フィールドを使用してaggregate
クエリ内で並べ替え、最後に使用されたドキュメントが最初に提供されるようにします。以下のクエリを使用して、集計の後に使用updateOne
して、最後に使用されたフィールドをバンプします。そのため、読み取りリクエストごとに last_used フィールドの日付スタンプが変更されます。
updateOne(
{ _id: result['_id']},
{
$currentDate: { 'last_used': true },
$inc: { 'count_used': 1 }
}
)
私が抱えている問題は、クライアントが 5 つの同時要求を行い、ドキュメント 1,2,3,4,5 を受け取る代わりに、たとえば 1,1,1,2,2 を取得することです。
これは、読み取りと更新の間にロックがないためであると推測しているため、更新が実行される前に複数の読み取りが同じ結果になります。
これを回避する方法はありますか?
以下の集計 nodejs コードで更新します
db.collection('testing').aggregate([{
$project: {
last_used : 1,
count_used : 1,
doc_type : 1,
_id : 1,
data : 1,
is_type : { $setIsSubset: [ [type], '$doc_type' ] }
}
},
{ $match: {
$or: query}
},
{ $sort: {
is_type: -1,
last_used: 1
}
},
{
$limit: 1
} ]).next(function (error, result) {
db.collection('adverts').updateOne({_id: result['_id']}, {$currentDate: {'last_used': true}, $inc: {'count_used': 1}})
}
問題は、複数の同時要求を発行する同じクライアントから複数の読み取り要求が来ることです。つまり、それらは同時に db にヒットし、起動する前に同じデータを読み取りupdateOne
ます。