在 MongoDB 中添加唯一索引忽略空值

Posted

技术标签:

【中文标题】在 MongoDB 中添加唯一索引忽略空值【英文标题】:Adding unique index in MongoDB ignoring nulls 【发布时间】:2013-05-31 13:43:00 【问题描述】:

我正在尝试在 MongoDB 中的一组字段上添加唯一索引。并非所有这些字段在所有文档中都可用,我只想索引具有所有字段的那些。

所以,我正在尝试运行这个:

db.mycollection.ensureIndex(date:1, type:1, reference:1, sparse: true, unique: true)

但我在缺少“类型”字段的字段上收到错误E11000 duplicate key error index(其中有很多而且它们是重复的,但我只想忽略它们)。

在 MongoDB 中是否可行或有一些解决方法?

【问题讨论】:

sparse 意味着不要索引缺少您要索引的字段的文档。除非您想跳过没有设置任何字段的文档,否则这对复合索引没有意义。 @AsyaKamsky 是的,我知道它是如何工作的,我正在寻找解决这个限制的方法。 已经在同一问题上提交了一个错误:jira.mongodb.org/browse/SERVER-2193 这里有很好的解释:***.com/questions/7955040/… 【参考方案1】:

唯一性,你可以保证,使用 upsert 操作而不是插入。这将确保如果某些文档已经存在,那么如果文档不存在,它将更新或插入

test:Mongo > db.test4.ensureIndex( a : 1, b : 1, c : 1, sparse : 1)

test:Mongo > db.test4.update(a : 1, b : 1, $set :  d : 1, true, false)
test:Mongo > db.test4.find()
 "_id" : ObjectId("51ae978960d5a3436edbaf7d"), "a" : 1, "b" : 1, "d" : 1 
test:Mongo > db.test4.update(a : 1, b : 1, c : 1, $set :  d : 1, true, false)
test:Mongo > db.test4.find()
 "_id" : ObjectId("51ae978960d5a3436edbaf7d"), "a" : 1, "b" : 1, "d" : 1 
 "_id" : ObjectId("51ae97b960d5a3436edbaf7e"), "a" : 1, "b" : 1, "c" : 1, "d" : 1 

【讨论】:

这是倒退的。如果所有三个字段都不存在,他希望允许重复。如果只有三分之二的字段存在,则使用 upsert 将防止重复 - 加上这将使逻辑显着复杂化,因为每个插入都需要检查要插入的文档,以针对三个字段中的哪一个进行更新。另外,当您想针对文档的不同属性进行真正的 upsert 时会发生什么? 如果文档中都存在所有三个键(插入),则可以通过执行 upserts(而不是 insert)轻松解决此问题,我想从应用程序中检查很容易。休息我从不谈论表演。但是给定这些字段上的索引不会是一个巨大的性能问题,因为在正常插入中,您也将更新索引,因此必须将其带到 RAM 中。这个解决方案只是被建议作为一种解决方法。 当您需要基于不同的值(例如基于用户名或 id 或 ...)进行更新插入时会发生什么? 我只在所有 3 个键都存在时才进行 upserts,以确保唯一性,否则它只是一个正常的插入 你不认为他的应用程序可能需要进行更新和插入吗?【参考方案2】:

有很多人想要这个功能,因为没有解决方法,我建议在 jira.mongodb.org 中投票支持功能请求 Jira 票证:

SERVER-785 - 支持过滤(部分)索引 SERVER-2193 - 稀疏索引只支持单个字段

请注意,由于 785 将提供一种强制执行此功能的方法,因此 2193 被标记为“不会修复”,因此投票并将您的 cmets 添加到 785 可能更有效率。

【讨论】:

是的,我在这里没有收到明确的答案后也找到了它。我会接受这一点,因为虽然 upsert 是一种可行的替代方案,但它只是一种替代方案,并不能真正模仿所需的行为。

以上是关于在 MongoDB 中添加唯一索引忽略空值的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb 唯一索引

添加索引迁移中的唯一性被忽略

在 NodeJS 中使用 Mongoose + Mockgoose 更新时忽略唯一索引

唯一索引不适用于 Mongoose / MongoDB

用于创建表并在两个字段上添加唯一索引的 Rails 迁移文件在迁移期间似乎被忽略了

MongoDb在并非所有文档中的字段上创建唯一索引[重复]