MongoDB可选唯一索引

时间:2016-03-03 11:09:31

标签: mongodb indexing

对于看起来像这样的用户,我有一个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会为duplicate key引发null错误}值(例如,如果有第二个用户提供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"}插入其他用户,则应该存在重复的密钥错误

我还能怎样做到这一点?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

索引a,c - 不能稀疏,因为它是唯一的.....

索引b,c - 不能稀疏,因为它是唯一的.....

索引a,b,c怎么样?

  

db.benjiman.insert({userId:" some-string",anonymousId:   " some-other-string",project:{" _oid":" 56d06bb6d9f75035956fa7ba"}   })

     

db.benjiman.insert({userId:" some-string2",project:{" _oid":   " 56d06bb6d9f75035956fa7ba"}})

     

db.benjiman.insert({anonymousId:" some-other-string2",project:   {" _oid":" 56d06bb6d9f75035956fa7ba"}})

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