2012-02-22 115 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