Mongodb和Mongoose错误:E11000重复键错误索引

时间:2017-07-22 01:27:37

标签: node.js mongodb mongoose

所以我一直在做一个项目,我完成了大部分工作,但随后出现了这个错误,说有些内容未定义,这是错误:

E11000 duplicate key error index: build-a-voting-app.polls.$votedIp_1 dup key: { : undefined }

这是我创建新mongo架构文件的代码(polls.model.js)

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const pollSchema = new Schema({
title: { type: String, unique: true, required: true },
choices: [
    {
        title: { type: String, required: true },
        count: { type: Number, default: 0 }
    }
],
votedIp: [{ type: String, unique: true }],
createdAt: {type:Date, default:Date.now()},
createdBy: String
});

const Poll = mongoose.model('polls', pollSchema);

module.exports = Poll;

这是我添加输入的功能

function submitVote(field, res, ip) {

Poll.findOneAndUpdate(
    { choices: { $elemMatch: { title: field } } },
    { $inc: { 'choices.$.count': 1 }, $addToSet: { 'votedIp': ip } },
    { new: true },
    function (err, poll) {
        if (err) throw err;
        res.json({ updated: poll });
    }
);
}

这是我第一次创建它的方式

var newPoll = new Poll({
    title: req.body.title,
    choices: choicesArr,
    createdBy: req.session.user.username || req.session.user
}).save(function (err, poll) {
    if (err) throw err
    res.redirect('/mypolls')
});

如果您想查看完整代码,请转到https://github.com/ElisaLuo/Freecodecamp-Build-A-Voting-App

我使用ip地址检查用户是否已投票(我正在构建一个投票应用),但是现在,我甚至无法创建新的架构/民意调查。有谁知道错误发生的原因以及如何解决它?

2 个答案:

答案 0 :(得分:1)

@Elisa l - 您可能希望阅读此内容 - mongoose enforce unique attribute on subdocument property

但是,我确实设法使用mongoose-mock进行测试并且行为符合预期 - 下面的测试结果(请在测试代码片段中检查两个版本的votedIp)

enter image description here

并且如上面链接中引用的MongoDb文档中所述。 Mongoose不会强制执行唯一的完整性,MongoDb会这样做。

使用下面的mocha测试(作为片段插入,不是为了更好的可读性而运行代码,请忽略代码中注释的混乱外观,但必须解决排列和组合!),我做了通过在“Poll”中添加create方法来管理创建mongoose模式。请注意架构中的更改 - votedIp:{type:String,unique:true} ,您可以在测试代码中将其更改为数组。

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var pollSchema = new Schema({
title: { type: String, unique: true, required: true },
choices: [
    {
        title: { type: String, required: true },
        count: { type: Number, default: 0 }
    }
],
votedIp: { type: String, unique: true },
createdAt: {type:Date, default:Date.now()},
createdBy: String
});
// Below code added by RJv (ie. me :)
var NewPoll = new mongoose.Schema(pollSchema);
NewPoll.statics.create = function (params, callback) {
  var newUpdate = new NewPoll(params);
  newUpdate.save(function(err, result) {
    callback(err, result);
  });
  return newUpdate;
};
var Poll = mongoose.model('Model', NewPoll);
module.exports = Poll;

var expect = require('chai').expect,mongooseMock = require('mongoose-mock'),proxyquire=require('proxyquire'),
sinon = require('sinon'), chai=require('chai'),sinonChai = require("sinon-chai");chai.use(sinonChai);

var Poll;
before(function(done){
        Poll = proxyquire('./Poll', {'mongoose': mongooseMock});
        done();
})
describe('model', function() {
        /*	beforeEach(function (done) {
	           Poll = proxyquire('./Poll', {'mongoose': mongooseMock});
                done();	
        });*/
it("should be called once",function(done){
        setTimeout(done, 15000);
        var callback = sinon.spy();
        var poll1 = Poll.create({ "title": 'jv', "choices": [{"title":"jv@gmail.com","count":"1"}],
            "votedIp":"9.1.2.1","createdAt":"23/07/2017","createdBy":"Lisa"}, callback);
    
        // Below to pass data for votedIp as an array as described in the original schema by Elisa 
        //"votedIp":[{"add1":"9.","add2":"1.","add3":"2.","add4":"1"}],"createdAt":"23/07/2017","createdBy":"Lisa"}, callback);
        //expect(poll1.votedIp[0].add1+poll1.votedIp[0].add2+poll1.votedIp[0].add3+poll1.votedIp[0].add4).equals("9.1.2.1");
                            
        expect(poll1.save).calledOnce;
        console.log(JSON.stringify(poll1));
        expect(poll1.votedIp).equals("9.1.2.1");
                    
        done(); 
});
it('should expect same ip to get added', function(done) {
        this.timeout(5000);
        setTimeout(done, 15000);

		var callback = sinon.spy();//mock(new Poll({ title: 'jv', choices: [{title:"jv@gmail.com","count":"1"}], votedIp:[{ad1:"9.",add2:"1.",add3:"2.",add4:"1"}],createdAt:"25/07/2017",createdBy:"Lisa"}));
        var poll = Poll.create({ "title": 'jv', "choices": [{"title":"jv@gmail.com","count":"1"}],
            "votedIp":"9.1.2.1","createdAt":"23/07/2017","createdBy":"Lisa"}, callback);
        // var poll = Poll.create({ "title": 'jv', "choices": [{"title":"jv@gmail.com","count":"1"}],

        // Below to pass data for votedIp as an array as described in the original schema by Elisa 
        //            "votedIp":[{"add1":"9.","add2":"1.","add3":"2.","add4":"1"}],"createdAt":"25/07/2017","createdBy":"Lisa"}, callback);
                // expect(poll.votedIp[0].add1+poll.votedIp[0].add2+poll.votedIp[0].add3+poll.votedIp[0].add4).equals("9.1.2.1");
        expect(poll.save).calledOnce;                                      
        expect(poll.votedIp).equals("9.1.2.1");  
    
        //assert(spy.calledOnce);
        done();
    });
});

答案 1 :(得分:0)

您是否连续多次致电submitVote?您可能会遇到https://jira.mongodb.org/browse/SERVER-14322

建议的解决方法是检查错误,如果其中一个调用失败则重试。

https://docs.mongodb.com/manual/reference/method/db.collection.update/#use-unique-indexes