2016-03-03 128 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