我希望我有一个很棒的大脑时刻。但这是我在刮痧中的情况;
我希望能够抓住多台机器和核心。每个站点,我有不同的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?如果是这样,我怎样才能将内容推送到嵌入式文档集合中,而不是同时覆盖其他所有内容,但如果尚未创建默认值,仍会创建默认值?
感谢您帮助我指导正确的方向!我真的希望我有一个巨大的脑力......
答案 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上的设计模式。