mongodb索引嵌入字段(点表示法)

Tzu*_*hay 7 mongodb

我们假设这是一个代表客户的文档.

{
    company_name: 'corporate ltd.',
    pocs: [
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Jessica', email: 'jessica@corporate.com'}
    ]
}
Run Code Online (Sandbox Code Playgroud)

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

db.things.ensureIndex({"pocs.email": 1}, {unique: true})
Run Code Online (Sandbox Code Playgroud)

奇怪的是,当试图添加另一家公司,其中有一个电子邮件已经存在于另一家公司时,mongo拒绝这一点,尊重唯一索引约束.

也就是说,以下内容不存在:

{
    company_name: 'corporate ltd.',
    pocs: [
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Jessica', email: 'jessica@corporate.com'}
    ]
},
{
    company_name: 'contoso llc',
    pocs: [
       {name: 'Paul', email: 'paul@corporate.com'},
    ]
}
Run Code Online (Sandbox Code Playgroud)

哪个好.但是,在同一文档中具有重复的poc是可能的,例如

{
    company_name: 'corporate ltd.',
    pocs: [
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Jessica', email: 'jessica@corporate.com'}
    ]
},
Run Code Online (Sandbox Code Playgroud)

请参阅下面的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: 'me@comapny.com'}]})
> db.test.insert({company: "contoso", poc: [{email: 'me@comapny.com'}]})
E11000 duplicate key error index: test.test.$poc.email_1  dup key: { : "me@comapny.com" }
> ({company: "contoso", poc: [{email: 'me.too@comapny.com'}, {email: 'me.too@company.com'}]})
> 
> 
> db.test.find()
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [ { "email" : "me@comapny.com" } ] }
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "me.too@comapny.com" }, { "email" : "me.too@company.com" } ] }
Run Code Online (Sandbox Code Playgroud)

而且,这发生在insert或在update.

> db.test.update({"_id" : ObjectId("4f44949685926af0ecf9295d")}, {$push: { poc: {email: 'me@company.com'}}})
> db.test.find()
{ "_id" : ObjectId("4f4494b885926af0ecf9295f"), "company" : "contoso", "poc" : [ { "email" : "me.too@comapny.com" }, { "email" : "me.too@company.com" } ] }
{ "_id" : ObjectId("4f44949685926af0ecf9295d"), "company" : "contoso", "poc" : [        {       "email" : "me@comapny.com" },   {       "email" : "me@company.com" },   {       "email" : "me@company.com" } ] }
> 
Run Code Online (Sandbox Code Playgroud)

这是一个错误设计功能,我错过了在文档中发现?

Ram*_*Vel 8

关于在单个文档的数组中未强制执行的相同问题唯一索引存在未解决的问题.你可以投票支持它.

此外,Kyle Banker在这个类似的帖子中提出了一个很好的解决方法,即嵌入式文档的唯一索引

更新

这不仅与嵌入字段有关,我们也可以为数组字段重现相同的字段.

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

如果我们尝试创建具有相同值的新文档(正确行为),则会引发错误

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

但是如果我们在数组中放入相同的值(没有错误,默默地接受数组中的重复值),这可以正常工作

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

但不是为了这个

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

  • +1.它被认为是一个错误,但非常奇怪."唯一索引旨在强制只有1个文档具有该密钥.从技术上讲,这种情况确实如此,但在大多数人使用该功能的方式中,他们希望包含子文件的唯一性." 我想知道他们是否可以修复它,因为这是一个非常大的语义变化,可能会咬人. (2认同)