2013-10-30 39 views
0

我在Python中使用MongoEngine來處理我的數據模型。追加到文檔內的列表中的子文檔中的列表?

我有一個數據模型基本上看起來像這樣在BSON表示:

{ 
    'id': ... 
    'revisions': [ 
     { 
      'id': ... 
      'revision': 1, 
      'derivatives': [ 
       { 
        'id': ... 
        'name': 'Derivative 1' 
       } 
      ] 
     } 
    ] 
} 

我們會打電話給owner最外面的文件,在owner.revisions所有的子文檔將被稱爲revision,並在revision.derivatives所有的子文檔將被稱爲derivative

我期待$addToSetderivatives設置在特定owner內的特定revision內。如果讓我用Python寫這個,它會是這樣的:

def add_to_set(owner_id, revision_id, new_derivative): 
    for owner in owner_collection: 
     if owner.id == owner_id: 
      # found the right owner 
      for revision in owner.revisions: 
       if revision.id == revision_id: 
        # we've found the right revision in the right owner 
        # now append and get out 
        revision.derivatives.append(new_derivative) 
        return 

我怎樣才能運行此類型的查詢,選擇合適的revisionowner內並自動追加到內derivatives收集上那revision

很難弄清楚如何開始使用像這樣的更新查詢。

回答

0

問題是使用保存基於舊版本的對象 - 它不是線程安全的。

您想要使用update運算符,它基於匹配的條件原子地操縱對象,而不是單方面用整個新對象覆蓋對象(由_id)。

的不安全 「保存」 示例:

線程1:讀取對象,具有字段{_id:1, a:1},遞增,節省{_id:1,a:2}
線程2:與現場{_id:1, a:1}讀取對象,遞增一個,節省{_id:1,a:2}

對比度這與「安全」更新:

線程1:更新對象匹配{_id:1}使用運算符{$inc:{a:1}}
線程2:更新對象使用操作者{$inc:{a:1}}

無論兩個線程在第二種情況下執行以什麼順序匹配{_id:1}的值將是2(因爲其將通過1在服務器上遞增兩次。

我猜你的對象正在發生同樣的事情 - 你想要的類似更新操作是$push operator

+0

你能提供一個實際的例子嗎?我不知道如何繼續。我會更新這個問題。 –

+0

我知道_why_問題正在發生,我不知道如何實施解決方案。 –

+0

除非您在應用程序端實施某種鎖定,否則無法使用保存並使其保持線程安全。另一種方法是切換到使用「更新」而不是「保存」 –

相關問題