2011-09-07 159 views
0

文檔結構是這樣的,

{ 
    blacklists:[]   // elements should be unique 
    blacklistsLength:0 // length of blacklists 
} 

增加套價值blacklists容易。

db.posts.update({_id:...}, {$addtoSet:{blacklists:{$each:['peter', 'bob', 'steven']}}}); 

但是,如何在同一時間更新blacklistLength以反映更改?

回答

1

請問下面不行嗎?

db.posts.update({_id:...}, { 
    $addtoSet:{blacklists:{$each:['peter', 'bob', 'steven']}}, 
    $set: {blacklistsLength: ['peter', 'bob', 'steven'].length} 
}); 
+2

如果有重複,它不起作用。 – Alice

3

這是不可能的。要麼你有長度seperately使用後續findAndModify 命令或

  • 你能做到每名並重寫使用否定查詢在 您的標準和$推動,而不是$ addToSet

    1. 更新(不一定 必要的,但速度快了很多大的黑名單,因爲addToSet是 總是O(N),無論指數):

      db.posts.update({_id:..., blacklists:{$ne:'peter'}}, {$push:{blacklists:{'peter'}},$inc:{blacklistsLength: 1}}); 
      

    後者是完全安全的,因爲列表和長度都是原子調整的,但顯然性能略有下降。由於$ push與$ addToSet在大型數組上的性能問題相比還具有更好的整體性能(並且黑名單往往會變得很大,並且記住$ push版本的更新在更新條件中的黑名單上使用索引,而$ addToSet在設置掃描期間不會使用索引),它通常是最好的解決方案。

  • 0

    當您將項目插入數據庫時​​,只需查詢項目以查看它是否在嵌入式數組中。這樣,您可以避免推送重複項目,並且只會在添加新項目時增加計數器。

    q = {'blacklists': {'$nin': ['blacklist_to_insert'] }} 
    u = { 
    '$push' : {'blacklists': { 'blacklist_to_insert' } }, 
    '$inc' : {'total_blacklists': 1 } 
    } 
    o = { 'upsert' : true } 
    
    db.posts.update(q,u,o)