使用sparse:true仍然得到MongoError:E11000重复键错误

tht*_*gma 5 mongoose mongodb node.js

架构(../models/add.js)

var addSchema = new Schema({
    name: {type: String, unique: true, sparse: true},
    phone: Number,
    email: String,
    country: Number
});

module.exports = mongoose.model('Contact', addSchema);
Run Code Online (Sandbox Code Playgroud)

附加manager.js

var Add = require('../models/add.js');
var AM = {};
var mongoose = require('mongoose');
module.exports = AM;

AM.notOwned = function(country, callback)
{
    Add.update({country: country}, {country: country}, {upsert: true}, function(err, res){
        if (err) callback (err);
        else callback(null, res);
    })
}
Run Code Online (Sandbox Code Playgroud)

news.js

// if country # is not in the database
    AM.notOwned(country, function(error, resp){
        if (error) console.log("error: "+error);
        else 
        {
            // do stuff
        }
    })
Run Code Online (Sandbox Code Playgroud)

错误:

MongoError: E11000 duplicate key error index: bot.contacts.$name_1  dup key: { : null }
Run Code Online (Sandbox Code Playgroud)

看到错误消息后,我四处搜索并了解到,在创建文档时,由于未设置name,因此将其视为null.请参阅Mongoose Google Group Thread 第一次调用AM.notOwned时,它将起作用,因为没有名称键的集合中没有任何文档.然后,AM.notOwned将插入带有ID字段和国家/地区字段的文档.

后续的AM.notOwned调用失败,因为已经存在没有名称字段的文档,因此将其视为name:null,并且调用第二个AM.notOwned失败,因为未设置字段"name"并将其视为null ; 因此它不是唯一的.

因此,遵循Mongoose线程的建议并阅读mongo文档,我使用sparse:true查看.但是,它仍然抛出相同的错误.进一步寻找到它,我想这可能是相同的问题:这个,但设置架构名称:{类型:字符串,索引:{独特:真正的,稀疏:真正}}没有解决它的.

这个问题/答案让我相信它可能是由索引不正确引起的,但我不太确定如何从Mongo控制台读取db.collection.getIndexes().

db.contacts.getIndexes()
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "ns" : "bot.contacts",
        "name" : "_id_"
    },
    {
        "v" : 1,
        "key" : {
            "name" : 1
        },
        "unique" : true,
        "ns" : "bot.contacts",
        "name" : "name_1",
        "background" : true,
        "safe" : null
    }
]
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能解决此错误?

Joh*_*yHK 5

您需要在shell中删除旧的非稀疏索引,以便Mongoose可以sparse: true在下次运行应用程序时重新创建它.

> db.contacts.dropIndex('name_1')
Run Code Online (Sandbox Code Playgroud)