用atomocuments原子创建mongodb文件?

时间:2013-07-21 17:24:58

标签: node.js mongodb parallel-processing mongoose database-schema

我希望我有一个很棒的大脑时刻。但这是我在刮痧中的情况;

我希望能够抓住多台机器和核心。每个站点,我有不同的Front页面,我刮了(exmpl。对于站点stackoverflow我有前端stackoverflow.com/questions/tagged/javascript和stackoverflow.com/questions/tagged/nodejs).

每个article都可以Front,当我发现一篇文章时,如果网址未知,我想要创建一个Article,如果知道我想创建Front如果article.discover未知,请在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]
});

我想我最终会遇到的问题是竞争条件。当两个求职者(并行)找到相同的(在未知之前)文章并创建一个新文章。是的,我有一个独特的索引,可以这样处理 - 非常不优雅的imho。

但是,让我们走得更远;何时 - 出于什么原因 - 我的两个职业选手同时在同一个方面刮擦,并且都注意到Front还没有进入并创建一个新的FrontDiscovery,我'd以同一Front的两个条目结尾。

你有什么策略来规避这种情况? findByIdAndUpdate with upsert:对于每个文件分别为true?如果是这样,我怎样才能将内容推送到嵌入式文档集合中,而不是同时覆盖其他所有内容,但如果尚未创建默认值,仍会创建默认值?

感谢您帮助我指导正确的方向!我真的希望我有一个巨大的脑力......

1 个答案:

答案 0 :(得分:1)

使用upsert=true进行更新可用于执行原子“插入或更新”(http://docs.mongodb.org/manual/core/update/#update-operations-with-the-upsert-flag)。

例如,如果我们想要确保Front集合中具有特定url的文档只插入一次,我们可以运行类似:

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

MongoDB中单个文档的操作总是原子的。如果您进行跨越多个文档的更新,则不保证原子性。在这种情况下,你可以问自己:我真的需要操作是原子的吗?如果答案是否定的,那么您可能会找到处理潜在不一致数据的方法。如果答案是肯定的并且您想坚持使用MongoDB,请查看Two Phase Commits上的设计模式。