15

書類を持ってきました

{ key : 'key1', value : 'value1', update_time : 100 }

最近の(より大きな)更新時間でのみ変更したいと思います。私が今していることは次のとおりです。

def update_key1(new_value, new_time):
    record = find_one( { key : 'key1' } )
    if not record or record['update_time'] < new_time:
        update( { key : 'key1', value : new_value, update_time : new_time }, upsert=True)

明らかに、これはデータベースへの余分なラウンドトリップですが、さらに重要なことは、ドキュメントにロックがなく、同時呼び出しによりデータベースに残る new_time の値が低くなる可能性があることです。条件が真の場合にのみアップサートを実行する方法はありますか?

編集: 明確にするために、キーごとに複数のドキュメントを作成してルックアップでソートすることは意図していません。それは私の問題を解決しますが、これらの値は大きく変化し、多くのスペースを浪費します。

4

5 に答える 5

2

すべてをアトミックに実行できるのではなく、変更を加えたい既存の条件が 2 種類あり、それぞれをアトミックに処理できます。

  • キーのレコードが存在しません
  • キーのレコードが存在し、そのレコードupdate_timeはより古いnew_time

キーの既存のレコードを更新します。

def update_if_stale(key, new_value, new_time):
    collection.update({'key': key,
                       'update_time': {'$lt': new_time}
                       },
                      {'$set': {'value': new_value,
                                'update_time': new_time
                                }
                       }
                      )

キーのレコードが以前に存在しなかった場合に挿入します。

def insert_if_missing(key, new_value, new_time):
    collection.update({'key': key},
                      {'$setOnInsert': {'value': new_value,
                                        'update_time': new_time
                                        }
                       },
                      upsert=True
                      )

( $setOnInsertMongoDB 2.4 で追加されました)

これらを組み合わせて、必要なものを取得できる場合があります。たとえば、次のようになります。

def update_key(key, new_value, new_time):
    insert_if_missing(key, new_value, new_time)        
    update_if_stale(key, new_value, new_time)

ただし、システムで可能な削除/挿入時間スケールに応じて、複数の呼び出し (更新/挿入/更新) またはその他のシェナニガンが必要になる場合があります。

余談: フィールドが欠落しているupdate_timeレコードを古いレコードとして処理して更新する場合は、次のように変更{'$lt': new_time}}します。{'$not': {'$gte': new_time}}

于 2013-10-06T23:01:20.463 に答える
1

upsert=True を使用した WPCoder の応答が探しているものではない場合は、まだ実装されていない $setOnInsert が必要になる場合があります: https://jira.mongodb.org/browse/SERVER-340。2.4.0 で実装する必要があります。

于 2012-12-07T19:50:20.787 に答える
0

findAndModifyを探しているようです。申し訳ありませんが、私はPythonに精通していないため、コードスニペットを提供することはできませんが、コマンドは非常に単純なはずです。

于 2012-12-07T15:34:31.947 に答える
0

条件付き更新を行うことができます:

db.MyObjects.update( { key : "key1", value: { $lt : aValue }},
                    { $set : { value : aValue }});
于 2012-12-07T19:13:59.037 に答える