2017-06-17 3 views
0

次のような場合があります。ドキュメントを特定のIDで更新し、そのupdate_timeが新しいものよりも古い場合、そうしたドキュメントが見つからない場合は、新しいドキュメントを作成する1。特定のクエリで更新する方が良い

私には最初の解決策は以下のとおりです。このソリューションで

db.collection.update(
    { 
    '_id': 'the_specific_id', 
    'update_time': {'$lt': new_date_time} 
    }, 
    { 
    '$set' :{ 
     'field_1': 'value_1', 
     'field_2': 'value_2', 
     'update_time': new_data_time 
    } 

    }, 
    { 'upsert': true} 
) 

ドキュメントが発見された場合、その後の更新は問題ありません。もし '_id'が見つからないためにdocが見つからなければ、upsertは問題ありません。しかし、dbの文書が新しい 'update_time'を持っているためにdocが見つからない場合は、次のupsertは(主キーの重複のため)正しくありません。

だから私は、この(psudoコード)で終わる必要があります:

try: 
    db.collection.insert({ 
    '_id': 'the_specific_id', 
    'field1': 'value1', 
    'field2': 'value2', 
    'update_time': new_date_time 
    }) 
except Exception as e: 
    if e.message.find('duplication'): 
     db.collection.update(
     { 
     '_id': 'the_specific_id', 
     'update_time': {'$lt': new_date_time} 
     }, 
     { 
      '$set' : { 
      'field_1': 'value_1', 
      'field_2': 'value_2', 
      'update_time': new_data_time 
      } 
     }, 
     { 'upsert': false}) 

これは複雑な上に見えます。私はこのソリューションでもっと良い方法があるのだろうか?

+0

は方法がありますが、あなたが「本当に」 '_id'フィールドを使用している場合、それはすでに「ユニーク」です、 "upsert" **は発生できません。重複したキーエラーを受け取り、何も変更されません。他の解決策も同じ原則で変わりますが、 '_id'は基本的にそれをカバーしており、この例では" upsert "は完璧です。 '$ set'や他の更新演算子がないと、実際には' 'update_time ''のような他のフィールドを "上書き"するので、実際には問題はありません。したがって、毎秒の書き込みはdupキーをアップして失敗させようとします。 –

+0

'$ set'演算子が追加されました –

+0

**重要** ** ** ** **プライマリキー**を複製することはできません。日付の不一致によりアップアップが発生することはありません。結果は常に重複キーエラーになります。あなたが望むものを達成する方法の本質は何ですか。あなたが真実をここに伝えているならば、「アップサート」はすでに働いています。 –

答えて

0

最初に検索を制限して、新しい更新時間より短い更新を持つアイテムのみを検索することができます。これらの選択が満たされたら、前と同じようにupsertを使用できます。

db.collection.update(
    { 
    '_id': 'the_specific_id', 
    'update_time': {'$lt': new_date_time} 
    }, 
    { 
    'field_1': 'value_1', 
    'field_2': 'value_2', 
    'update_time': new_date_time 
    }, 
    { 'upsert': true} 
) 
0

あなたは約束のために使用されるが、これはメカニズムを作成、更新のお手伝いをすることができますも{upsert:true}文が含まれているfindOrCreateを使用することができます。

ありがとうございました。

0

としては@Neil LUNNによって指摘、これを行う最も簡単な方法は次のとおりです。

try: 
    db.collection.update(
    { 
    '_id': 'the_specific_id', 
    'update_time': {'$lt': new_date_time} 
    }, 
    { 
    '$set' :{ 
    'field_1': 'value_1', 
    'field_2': 'value_2', 
    'update_time': new_data_time } 
    }, 
    {'upsert': true}) 
except DuplicateKeyError as e: 
    pass