2012-02-22 116 views
6

我们假设这是代表客户的文档。mongodb索引嵌入字段(点符号)

{ 
    company_name: 'corporate ltd.', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Jessica', email: '[email protected]'} 
    ] 
} 

我想定义一个唯一索引pocs.email 所以我发出以下命令:

db.things.ensureIndex({"pocs.email": 1}, {unique: true}) 

奇怪的是,尝试添加另一家公司用POC有一个电子邮件地址已存在时在另一家公司,mongo拒绝这一点,尊重独特的索引约束。

也就是说,以下情况不能存在:

{ 
    company_name: 'corporate ltd.', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Jessica', email: '[email protected]'} 
    ] 
}, 
{ 
    company_name: 'contoso llc', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
    ] 
} 

这很好。然而,在同一文档中可能有重复的poc,例如,

{ 
    company_name: 'corporate ltd.', 
    pocs: [ 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Paul', email: '[email protected]'}, 
     {name: 'Jessica', email: '[email protected]'} 
    ] 
}, 

看到我的CLI命令下面的顺序:

> version() 
version: 2.0.2 
> 
> use test 
switched to db test 
> db.test.ensureIndex({"poc.email": 1}, {unique: true}) 
> 
> db.test.insert({company: "contoso", poc: [{email: '[email protected]'}]}) 
> db.test.insert({company: "contoso", poc: [{email: '[email protected]'}]}) 
E11000 duplicate key error index: test.test.$poc.email_1 dup key: { : "[email protected]" } 
> ({company: "contoso", poc: [{email: '[email protected]'}, {email: '[email protected]'}]}) 
> 
> 
> db.test.find() 
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" } ] } 
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" } ] } 

而且,这种情况无论是在insertupdate

> db.test.update({"_id" : ObjectId("4f44949685926af0ecf9295d")}, {$push: { poc: {email: '[email protected]'}}}) 
> db.test.find() 
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "[email protected]" }, { "email" : "[email protected]" } ] } 
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [  {  "email" : "[email protected]" }, {  "email" : "[email protected]" }, {  "email" : "[email protected]" } ] } 
> 

这是一个错误一个通过设计特征我错过了文档中的点滴?

回答

7

对于同样的问题unique indexes not enforced within array of single document有一个未解决的问题。你可以为它投票。

也有一个很好的解决办法在这个类似的帖子Unique indexes on embedded documents

更新

这不仅关系到嵌入式领域由凯尔银行家建议,我们可以重现相同的阵列领域了。

>db.uniqqueTest.insert({a:[1],x:1}) 
>db.uniqqueTest.createIndex({a:1}, {unique: true}) 
> db.uniqqueTest.find() 
{ "_id" : ObjectId("4f44c6252434860b44986b02"), "a" : [ 1 ],"x":1 } 

,如果我们试图创建一个具有相同值的新文件(正确的行为)

> db.uniqqueTest.insert({a:[1],x:3}) 
E11000 duplicate key error index: stack.uniqqueTest.$a_1 dup key: { : 1.0 } 

但是,如果我们把数组中的值相同这工作得很好,它抛出一个错误(无错误,默默接受阵列内的重复的值)

> db.uniqqueTest.insert({a:[2],x:2}) 
> db.uniqqueTest.update({x:2},{$push:{a:2}}) 
{ "_id" : ObjectId("4f44c65f2434860b44986b05"), "a" : [ 2, 2 ], "x" : 2 } 

但不是本

> db.uniqqueTest.update({x:2},{$push:{a:1}]) 
E11000 duplicate key error index: stack.uniqqueTest.$a_1 dup key: { : 1.0 } 
+2

+1。它被认为是一个错误,但是很奇怪。 “唯一的索引被设计用来强制执行只有一个文档拥有该密钥 从技术上讲,对于这种情况是这样的,但在大多数人使用该功能的方式中,他们希望独特的包含子文档。我不知道他们是否可以解决这个问题,因为这是一个非常大的语义变化,可能会咬人。 – Thilo 2012-02-22 08:04:25

+0

@Thilo,我完全同意你的看法。如果他们接受它,它将会是一个巨大的变化,完全与独特的索引应该是什么性质相矛盾。大多数人误解了嵌入/子文档作为真实文档的概念。这是真正的问题。但是'嵌入式doc只是另一个领域(具有嵌套属性),并且只具有与普通领域相同的特征。如果他们明白这一点,这些问题就不会发生 – RameshVel 2012-02-22 08:22:51

+0

@RameshVel或许这是一个观点问题,而不是[误解]理解概念。请参阅,如果嵌套数组有N个项目,则索引表中现在有N个条目,每个条目有一个条目。不像“唯一索引的性质”,它为每个记录的每个索引定义创建单个条目。 除此之外,如果我们要取出子文档并将它们放在一个单独的集合中,那么我们回到了从传统的RDBMS中知道的加入地狱。 – 2012-02-22 09:23:54