如何使用mongodb绕过唯一索引中的缺失值?

时间:2011-08-25 12:50:44

标签: mongodb

mongo文档声明“当文档保存到具有唯一索引的集合时,任何丢失的索引键都将插入空值。因此,将无法插入缺少相同索引键的多个文档。 “

那么在可选字段上创建唯一索引是不可能的?我应该用userId创建一个复合索引来解决这个问题吗?在我的特定情况下,我有一个具有可选嵌入式oauth对象的用户集合。 e.g。

>db.users.ensureIndex( { "name":1, "oauthConnections.provider" : 1, "oauthConnections.providerId" : 1 } );

我的示例用户<​​/ p>

{  name: "Bob"
   ,pwd: "myPwd"
   ,oauthConnections [
      {
         "provider":"Facebook",
         "providerId" : "12345",
         "key":"blah"
      }
     ,{
         "provider":"Twitter",
         "providerId" : "67890",
         "key":"foo"
      }
     ]
}

3 个答案:

答案 0 :(得分:11)

我认为这是可能的:您可以拥有稀疏且唯一的索引。这样,不存在的值永远不会进入索引,因此它们不能重复。

警告:复合索引无法做到这一点。我不太确定你的问题。您引用了涉及复合索引的文档的一部分 - 那里将插入缺失值,但是从您的问题我猜您不是在寻找具有复合索引的解决方案?

以下是一个示例:

> db.Test.insert({"myId" : "1234", "string": "foo"});
> show collections
Test
system.indexes
>
> db.Test.find();
{ "_id" : ObjectId("4e56e5260c191958ad9c7cb1"), "myId" : "1234", "string" : "foo" }
>

> db.Test.ensureIndex({"myId" : 1}, {sparse: true, unique: true});
>
> db.Test.insert({"myId" : "1234", "string": "Bla"});
E11000 duplicate key error index: test.Test.$myId_1  dup key: { : "1234" }
>
> db.Test.insert({"string": "Foo"});
> db.Test.insert({"string": "Bar"});
> db.Test.find();
{ "_id" : ObjectId("4e56e5260c191958ad9c7cb1"), "myId" : "1234", "string" : "foo" }
{ "_id" : ObjectId("4e56e5c30c191958ad9c7cb4"), "string" : "Foo" }
{ "_id" : ObjectId("4e56e5c70c191958ad9c7cb5"), "string" : "Bar" }

另请注意compound indexes can't be sparse

答案 1 :(得分:2)

索引可选字段并非不可能。文档正在讨论唯一索引。一旦指定了唯一索引,即使该值为null,也只能为该字段的每个值插入一个文档。

如果你想要一个可选字段的唯一索引但仍然允许多个空值,你可以尝试使索引既独特又稀疏,虽然我不知道是否可能。我在文档中找不到答案。

答案 2 :(得分:1)

没有好的方法来唯一索引可选字段。您可以使用默认值填充它(用户上的_id可以使用),让您的访问层强制执行唯一性,或者更改您的&#34;架构&#34;一点。

我们有一个单独的oauth登录令牌集合,部分原因就是这个原因。我们从来没有真正需要访问那些将它们作为嵌入式文档显然获胜的环境。如果这是一个相对容易的改变,那么它可能是你最好的选择。

---- ----编辑

正如其他答案所指出的那样,您可以使用稀疏索引实现此目的。它甚至是有记录的用途。你应该接受其中一个而不是我的答案。

http://www.mongodb.org/display/DOCS/Indexes#Indexes-SparseIndexes