我需要对嵌套文档强制执行唯一约束,例如:
urlEntities: [
{ "url" : "http://t.co/ujBNNRWb0y" , "display_url" : "bit.ly/11JyiVp" , "expanded_url" :
"http://bit.ly/11JyiVp"} ,
{ "url" : "http://t.co/DeL6RiP8KR" , "display_url" : "ow.ly/i/2HC9x" ,
"expanded_url" : "http://ow.ly/i/2HC9x"}
]
url,display_url和expaned_url需要是唯一的。如何在MongoDB中为这个条件发出ensureIndex命令?
此外,拥有这样的嵌套文档是一个很好的设计,还是应该将它们移动到一个单独的集合中,并在urlEntities中从这里引用它们?我是MongoDB的新手,任何最佳实践建议都会有所帮助。
完整场景:
假如我在数据库中有如下文档,其中包含数百万个数据:
{“_ id”:{“$ oid”:“51f72afa3893686e0c406e19”},“user”:“test”,“urlEntities”:[{“url”:“http://t.co/64HBcYmn9g”,“display_url”:“ ow.ly/nqlkP“,”expanded_url“:”http://ow.ly/nqlkP“}],”count“:0}
当我得到另一个具有类似urlEntities对象的文档时,我只需要更新用户和计数字段。首先我想在urlEntities字段上强制执行唯一约束,然后处理异常然后进行更新,否则如果我在插入之前检查每个条目是否存在,它将对性能产生重大影响。那么,我如何在urlEntities中强制执行唯一性?我试过了
{"urlEntities.display_url":1,"urlEntities.expanded_url":1},{unique:true}
但我仍然可以两次插入同一文档而无例外。
另外,请建议任何更好的方法来处理这种情况。
感谢。
答案 0 :(得分:1)
唯一性仅强制执行每文档。您无法阻止以下操作(从您的示例中简化):
db.collection.ensureIndex( { 'urlEntities.url' : 1 } );
db.col.insert( {
_id: 42,
urlEntities: [
{
"url" : "http://t.co/ujBNNRWb0y"
},
{
"url" : "http://t.co/ujBNNRWb0y"
}
]
});
类似地,嵌套文档的复合唯一键也会遇到同样的问题。
可以做的事情如下:
db.collection.insert( {
_id: 43,
title: "This is an example",
} );
db.collection.update(
{ _id: 43 },
{
'$addToSet': {
urlEntities: {
"url" : "http://t.co/ujBNNRWb0y" ,
"display_url" : "bit.ly/11JyiVp" ,
"expanded_url" : "http://bit.ly/11JyiVp"
}
}
}
);
现在,您的文档包含_id 43
,其中包含一个urlEntities文档。如果您再次运行相同的更新查询 ,它将不添加新的数组元素,因为已经有url,display_url和expanded_url的完整组合存在。
另外,请查看$addToSet
查询运算符的示例:http://docs.mongodb.org/manual/reference/operator/addToSet/
答案 1 :(得分:0)
对于嵌套文档的索引,请阅读this。
关于第二部分(嵌套文档最佳实践) - 它实际上取决于您的业务逻辑和查询。如果这些嵌套文档作为第一类实体没有意义,这意味着你不会直接搜索它们,而只是在它们的父文档的上下文中,那么将它们嵌套是有意义的。否则你应该考虑将它们删除。
我认为你的问题没有绝对的答案。阅读关于索引的章节...它对我帮助很大。