2016-03-03 73 views
2

我有用戶MongoDB的模式,它看起來是這樣的:MongoDB的可選唯一索引

{ 
    userId: "some-string", 
    anonymousId: "some-other-string", 
    project: {"$oid": "56d06bb6d9f75035956fa7ba"} 
} 

用戶必須具有一個userIdanonymousId。由於用戶屬於一個項目,該模型還有一個名爲project的引用,該引用鏈接到項目集合。

任何userIdanonymousId值必須是每個項目唯一的,所以我創建了兩個複合指標如下:

db.users.createIndex({ "userId": 1, "project": 1 }, { unique: true }) 
db.users.createIndex({ "anonymousId": 1, "project": 1 }, { unique: true }) 

然而,由於不能同時userIdanonymousId必須提供,但只是其中一方,MongoDB爲null值拋出duplicate key錯誤(例如,如果有第二個用戶提供了anonymousId但沒有userId)。

因此,我試圖給複合索引添加一個sparse: true標誌,但這顯然只適用於兩個字段都爲空的情況。我也嘗試將稀疏標誌僅添加到字段而不是複合索引,但這也不起作用。

舉個例子,假設我有以下三個用戶集合中:

{ userId: "user1", anonymousId: null, project: {"$oid": "56d06bb6d9f75035956fa7ba"}} 

{ userId: "user2", anonymousId: "anonym", project: {"$oid": "56d06bb6d9f75035956fa7ba"}} 

{ userId: "user3", anonymousId: "random", project: {"$oid": "56d06bb6d9f75035956fa7ba"}} 

下應該可以:

  • 我希望能夠插入其它用戶{userId: "user4", anonymousId: null}對於同一個項目(沒有得到重複鍵錯誤)
  • 但是,如果我嘗試插入另一個用戶{userId: "user3"}或另一個用戶{anonymousId: "random"}應該有一個複製te關鍵錯誤

我該怎麼做到這一點?

+0

您使用的是什麼版本的MongoDB? – Saleem

+0

我正在使用3.0.9。你是因爲部分索引而問的嗎? – benjiman

+0

確實。這是意圖,並將解決您的許多問題。如果可能,我會建議升級數據庫引擎。 – Saleem

回答

2

如果您使用的是MongoDB 3.2,則可以使用唯一部分索引而不是稀疏索引。

偏指數實際上建議在稀疏索引

db.users.createIndex({ "userId": 1, "project": 1 }, 
{ unique: true, partialFilterExpression:{ 
    userId: { $exists: true, $gt : { $type : 10 } } } }) 

db.users.createIndex({ "anonymousId": 1, "project": 1 }, 
{ unique: true, partialFilterExpression:{ 
    anonymouseId: { $exists: true, $gt : { $type : 10 } } } }) 

在上面的例子中,唯一索引將只當userId存在並且不包含空值創建的。同樣也適用於anonymousId

請參閱https://docs.mongodb.org/manual/core/index-unique/#unique-partial-indexes

+0

是的,我知道,但不幸的是,我不得不使用3.0.9版本。但是,你將如何使用部分索引來做到這一點? – benjiman

+0

那麼在這種情況下,你只有一個選項,我看到profesor79張貼上面。在所有三個字段上創建複合索引。 – Saleem

+0

你可以編輯你的答案給出一個例子如何在這種情況下創建一個獨特的部分索引? – benjiman

1

指數A,C - 這是唯一不能被稀疏.....

指數B,C - 這是唯一不能被稀疏.....

怎麼樣指數A,B ,C ?

db.benjiman.insert({用戶名: 「一些字符串」,anonymousId: 「一些,其他串」,項目:{ 「_oid」: 「56d06bb6d9f75035956fa7ba」}} )

db.benjiman.insert({用戶名: 「一些-字符串2」 項目:{ 「_oid」: 「56d06bb6d9f75035956fa7ba」}})

db.benjiman.insert({anonymousId: 「一些 - 其他 - 字符串2」項目: {「_oid」:「56d06bb6d9f75035956fa7ba」}})

db.benjiman.createIndex({ "userId": 1, "anonymousId": 1, "project": 1 }, { unique: true }) 
+0

我也考慮過這個問題,但是這種方法的問題是它允許插入相同的userId,例如,如果提供了不同的anonymousId。 – benjiman

+0

好的,現在有更大的圖片,讓我們在這裏聊聊http://chat.stackoverflow.com/rooms/104903/mongo-queries-issues – profesor79