0

我希望我有一個偉大的brainfart時刻。但這是我的情況,在szenario刮,使用子文檔自動創建mongodb文檔?

我希望能夠抓住多個機器和核心。每個網站,我有不同的Front頁,我刮(網站stackoverflow我有前面stackoverflow.com/questions/tagged/javascript和stackoverflow.com/questions/tagged/nodejs)。

article可以在每個Front,當我發現了一篇文章,我想創建一個Article如果URL是未知的,如果它知道我想在article.discoverFront條目;如果Front是未知的,否則插入我FrontDiscovery到適當的Front

這是我的模式;

FrontDiscovery = new Schema({ 
    _id   :{ type:ObjectId, auto:true }, 
    date  :{ type: Date, default:Date.now}, 
    dims  :{ type: Object, default:null}, 
    pos   :{ type: Object, default:null} 
}); 

Front = new Schema({ 
    _id   :{ type:ObjectId, auto:true }, 
    url   :{type:String}, //front 
    found  :[ FrontDiscovery ] 
}); 

Article = new Schema({ 
    _id   :{ type:ObjectId, auto:true }, 
    url   :{ type: String , index: { unique: true } }, 
    site  :{ type: String }, 
    discover:[ Front] 
}); 

問題我想我最終會遇到的是一種競爭條件。當兩個求職者(平行)找到相同的(未知的)文章並創建一個新文章。是的,我有一個獨特的索引,並可以這樣處理 - 非常不雅。

但讓我們走得更遠;當 - 由於某種原因 - 我的兩名工作人員同時在同一陣線上拼搶,並注意到對於Front還沒有入口,並創建一個新的加入FrontDiscovery,我會以兩個條目結束相同的Front

你有什麼策略來規避這種情況? findByIdAndUpdate和upsert:分別對每個文檔都是true?如果是這樣,我如何才能將內容推送到嵌入式文檔集合中,而不是同時覆蓋其他所有內容,但是如果尚未創建默認值,那麼仍然會創建默認值?

非常感謝您幫助我指導正確的方向!我真的希望我有一個巨大的brainfart ..

回答

1

更新upsert=true可用於執行原子「插入或更新」(http://docs.mongodb.org/manual/core/update/#update-operations-with-the-upsert-flag)。

舉例來說,如果我們要確保在前面收集特定url文檔插入只有一次,我們可以運行類似:在MongoDB中單個文檔

db.Front.update(
    {url: 'http://example.com'}, 
    {$set: { 
     url: 'http://example.com'}, 
     found: true 
    } 
) 

操作總是原子。如果您進行跨多個文檔的更新,則不保證原子性。在這種情況下,你可以問自己:我真的需要這些操作是原子嗎?如果答案是否定的,那麼你可能會找到解決潛在不一致數據的方法。如果答案是肯定的,並且您想堅持使用MongoDB,請查看Two Phase Commits上的設計模式。

+0

謝謝你的回答。但我現在有另一個問題; 如果我使用此代碼來查找文章(和Front),那麼它應該創建文章並推送一個新的Front,但是我得到一個「MongoError:無法對非數組應用$ push/$ pushAll修飾符 「錯誤 'dbArticle.findOneAndUpdate({ 網址:article.url, 」discover.url「:article.front },{ $ 設置:{ 網址:文章。URL, 網站:網站 }, $推:{ 發現:新dbArticleFront({ 網址:article.front })} , {UPSERT:真正}, 功能(ERR,結果){' – japrescott

+0

確保您的發現字段尚未設置爲不是數組的值 – christkv