3

以下の形式のドキュメントがいくつかあります

{
    "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ます。

4

0 に答える 0