Mongo 稀疏索引没有按我预期的那样工作

Lui*_*ira 2 indexing mongoose mongodb

我说“正如我所料”,因为我可能误解了它应该如何工作。

我有一个包含这样的对象的模型:

{
    "_id" : ObjectId("56408d76ef82679937000008"),
    "_type" : "ford",
    "year" : 1986,
    "model" : "sierra",
    "model_unique" : 1,
    "__v" : 0
}
Run Code Online (Sandbox Code Playgroud)

我需要一个复合唯一索引,除非指定_typemodel否则不允许插入具有相同和组合的两个对象。

我认为我可以指定的方式是使用model_unique列并使索引稀疏,因此两次添加前一个文档应该会失败,而应该允许以下内容(请注意,没有model_unique字段):

{
    "_id" : ObjectId("56408e0d636779c83700000a"),
    "_type" : "veridianDynamics",
    "year" : 1986,
    "model" : "sierra",
    "__v" : 0
}
{
    "_id" : ObjectId("another ID"),
    "_type" : "veridianDynamics",
    "year" : 2003,
    "model" : "sierra",
    "__v" : 0
}
Run Code Online (Sandbox Code Playgroud)

我认为这适用于这个索引:

Schema.index({"_type": 1, "model": 1, "model_unique": 1}, { unique: true, sparse: true });
Run Code Online (Sandbox Code Playgroud)

但它实际上失败了:

[MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: mongoose-schema-extend.vehicles.$_type_1_model_1_model_unique_1  dup key: { : "veridianDynamics", : "sierra", : null }]
Run Code Online (Sandbox Code Playgroud)

显然,它正在考虑未定义的字段具有空值。

我正在使用 mongod --version db version v2.6.11

npm -v mongoose 2.14.4

Joh*_*yHK 6

文档上的sparse复合索引:

仅包含升序/降序索引键的稀疏复合索引将索引文档,只要该文档包含至少一个键。

在您的情况下,这意味着只有当复合索引的所有三个组件都从文档中丢失时,文档才会从索引中排除,从而免于唯一约束。

因此,您尝试添加的稀疏索引将允许多个文档没有三个键中的任何一个,但对于所有其他情况,所有三个字段的组合必须是唯一的,任何缺失的字段都将获得null.

在您的示例文档中,从唯一索引的角度来看,它们都如下所示:

{
    "_type" : "veridianDynamics",
    "model" : "sierra",
    "model_unique : null
}
Run Code Online (Sandbox Code Playgroud)

因此,不是唯一的。

仅供参考,此规则有例外,其中复合稀疏索引中存在地理空间或文本索引,将规则更改为在确定是否将文档包含在索引中时仅考虑该特殊索引字段。