【问题标题】:mongodb indexing embedded fields (dot notation)mongodb索引嵌入字段(点表示法)
【发布时间】:2012-02-22 18:50:22
【问题描述】:

假设这是一个代表客户的文档。

{
    company_name: 'corporate ltd.',
    pocs: [
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Jessica', email: 'jessica@corporate.com'}
    ]
}

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

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

奇怪的是,当尝试使用 poc 添加另一家公司时,另一家公司中已经存在电子邮件,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'},
    ]
}

这很好。但是,同一文档中可能存在重复的 poc,例如

{
    company_name: 'corporate ltd.',
    pocs: [
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Paul', email: 'paul@corporate.com'},
       {name: 'Jessica', email: 'jessica@corporate.com'}
    ]
},

在下面查看我的 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" } ] }

此外,这发生在insertupdate

> 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" } ] }
> 

这是一个错误还是设计特性我错过了在文档中发现?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

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

    Kyle Banker 在类似的帖子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 }
    

    【讨论】:

    • +1。它被认为是一个错误,但非常奇怪。 “唯一索引旨在强制只有 1 个文档具有该密钥。从技术上讲,这对于这种情况是正确的,但在大多数人使用该功能的方式中,他们希望包含子文档的唯一性。”我想知道他们是否可以修复它,因为这是一个相当大的语义变化,可能会咬一些人。
    • @Thilo,我完全同意你的看法。如果他们接受它并且与唯一索引应该是的性质完全矛盾,那将是一个很大的变化。大多数人将嵌入/子文档的概念误解为真实文档。这才是真正的问题。但是embedded doc is just another field (with nested properties) and only have the same features as the normal fields。如果他们明白这一点,这些问题就不会出现
    • @RameshVel 也许这是一个观点问题,而不是[错误]理解概念。看,如果嵌套数组有 N 个项目,索引表中现在有 N 个条目,每个条目一个。与“唯一索引的性质”不同,它为每个记录的每个索引定义创建单个条目。不仅如此,如果我们要取出子文档并将它们放在一个单独的集合中,那么我们就会回到我们从经典 RDBMS 中知道的连接地狱。
    • @RameshVel:我认为将其视为错误是合理的。唯一应该意味着唯一,即使在同一文档中的多键字段中也是如此。但似乎之前没有人考虑过这一点,现在的行为已经融入其中,现在改变它可能比忍受它更麻烦。我们将看看结果如何。看票就行了。至于关于嵌入式文档的讨论,我们是否知道这只发生在嵌入式文档中?一个简单的顶级字段也不会发生这种情况吗?如果是这样,这与嵌入式文档无关。
    猜你喜欢
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 2020-07-20
    • 2011-08-28
    • 2016-11-23
    • 2012-02-22
    • 2020-09-18
    • 2015-06-24
    相关资源
    最近更新 更多