【问题标题】:Mongoose Compound Index Unique + SparseMongoose 复合索引唯一 + 稀疏
【发布时间】:2021-05-26 12:31:10
【问题描述】:

我想创建一个索引,以确保在 a manufacturer + art 的组合中没有重复的 serialNr。但有些项目没有serialNr。这些我不想检查/索引。

代码

mySchema.index({ serialNr: 1, art: 1 , manufacturer: 1, deleted: 1}, { unique: true, sparse: true)

我也尝试过添加部分过滤器: partialFilterExpression: { serialNr: {$ne:null} } 到索引选项。

问题

我怎样才能索引它插入: [{art: 'a', manufacturer:'a', deleted:null}, {art: 'a', manufacturer:'a', deleted:null}] 通过

[{serialNr: '123', art: 'a', manufacturer:'a', deleted:null}, {serialNr: '123', art: 'a', manufacturer:'a', deleted:null}]失败

我不想保存: [{serialNr: null, art: 'a', manufacturer:'a', deleted:null}, {serialNr: null, art: 'a', manufacturer:'a', deleted:null}]


mongo 文档指出,如果复合索引中缺少字段,则不应对其进行索引:

稀疏索引仅根据 索引字段的存在,或者对于复合索引,存在 的索引字段。 https://docs.mongodb.org/manual/core/index-partial/

编辑:

新索引

implantSchema.index({ serialNr: 1, art: 1 , manufacturer: 1, deleted: 1}, { unique: true, partialFilterExpression: { serialNr: {$exists:true} }})

在对索引进行更改之前,我将collection 放到我的开发数据库中,以确保不存在旧索引。这是db.items.getIndexes()返回的新索引

/* 0 */
{
    "0": {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "LOC_db.items"
    },
    "1": {
        "v" : 1,
        "unique" : true,
        "key" : {
            "serialNr" : 1,
            "art" : 1,
            "manufacturer" : 1,
            "deleted" : 1
        },
        "name" : "serialNr_1_art_1_manufacturer_1_deleted_1",
        "ns" : "LOC_db.items",
        "partialFilterExpression" : {
            "serialNr" : {
                "$exists" : true
            }
        },
        "background" : true
    }
}

数据

  • 我有一个预保存挂钩,我在其中检查 serialNr 的值,之前不存在,dup error 被返回。
  • 查询数据库时,不存在doc,它具有null"" 作为serialNr 的值。
  • 查询db.items.find({ serialNr: {$exists:true} }) 不匹配任何项目。

错误

insertDocument :: caused by :: 11000 E11000 duplicate key error index: LOC_db.items.$serialNr_1_art_1_manufacturer_1_deleted_1 dup key: { : null, : "Robo", : "Olymp", : null }

其他信息

可能该错误与: https://github.com/Automattic/mongoose/issues/2457

【问题讨论】:

  • 问题是什么?您已经回答了自己,使用具有稀疏性的唯一索引...另外,您为什么要删除索引?
  • 那行不通,这就是问题存在的原因。我索引已删除,因为它是即使用户删除它也需要保留的数据。因此,deleted 为 null 或用户删除数据的日期。
  • 实际上,如果删除日期,我不会在删除时保存“null”,这是错误的。

标签: node.js mongodb mongoose mongoose-schema


【解决方案1】:

您实际上已经非常接近解决方案,创建索引时您需要使用它:

partialFilterExpression: { serialNr: {$exists:true} }

确保至少有 3.2 版本的 mongo


例子:

db.col.createIndex({a:1, b:1},{unique:true, partialFilterExpression: { a: {$exists:true} })
db.col.save({a:50, b:27}) //pass
db.col.save({a:50, b:27}) //fails
db.col.save({b:27}) //pass
db.col.save({b:27}) //pass
db.col.save({b:27}) //pass
db.col.save({a:50, b:27}) //fails
db.col.save({a:50}) //pass
db.col.save({a:50}) //fails

PS:也许你可以做一点“hack”并使用它:partialFilterExpression: { serialNr: {$exists:true}, serialNr: {$gte:0} }

我尝试使用 $ne,但它给我一个错误。

【讨论】:

  • 我无法让它工作。我在上面添加了当前情况的编辑。
  • @AndiGiga - 您显然是在尝试添加文档,其中 serialNr 存在且值为 null ...您说您没有这样做。
  • 我在错误消息中也看到了null,但我没有传递null 值。如上面的编辑所述:先前保存的条目不包含任何 serialNr 值,当前保存的 doc 不包含预保存挂钩中的 serialNr 的任何值。
  • 我的版本是:"mongoose": "^4.0.2", 和 MongoDB shell 版本:是 2.6.6 我现在更新它们并检查错误是否仍然存在。
  • @AndiGiga - 你的猫鼬模型怎么样?如果您将serialNr 的默认值设置为null,它将传递null。所以把“default:null”去掉就可以了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-12
  • 1970-01-01
  • 2018-01-22
  • 2015-02-15
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多