猫鼬复合指数独特+稀疏

时间:2016-03-10 15:30:49

标签: node.js mongodb mongoose mongoose-schema

我想创建一个索引,确保在serialNr + manufacturer的组合中我没有重复art。但有些项目没有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 docs声明,如果复合索引中缺少某个字段,则不应编入索引:

  

稀疏索引选择仅根据文档索引的文档   索引字段的存在,或复合索引的存在   索引字段。   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放入我的dev-database中,以确保不存在旧索引。这是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

1 个答案:

答案 0 :(得分: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,但它给我一个错误。