Mongoose和唯一字段

66

我有以下使用mongoose定义的模式:

var SimSchema = new Schema({
    msisdn     : { type : String , unique : true, required : true },
    imsi       : { type : String , unique : true, required : true },
    status     : { type : Boolean, default: true},
    signal     : { type : Number },
    probe_name : { type:  String , required : true }
});

我有一个针对msisdnimsiunique选项。

在某些情况下,这个条件会被严格遵守。 对于以下的mocha测试:

"use strict";

var app      = require('../../app');
var http     = require('http');
var request  = require('supertest');
var mongoose = require('mongoose');
var should   = require('should');



describe('[ Sim controller ] ', function(){
  before(function(done) {
    app.set_env('test');
    this.server = app.start(function() {
      mongoose.connection.db.dropDatabase(function() {
        done();
      })
    });
  });


  beforeEach(function(done){
    done();
  });


  it('Sim with good parameters should be created in the database', function(done){
    var newSim = {
      msisdn:     '1234',
      imsi:       '007',
      probe_name: 'BOUCHON_1'
    };

    request(this.server)
      .post('/sims')
      .set('Content-Type', 'application/json')
      .send(newSim)
      .expect(200).end(function(err, res) {
        if (err) return done(err);
        res.body.should.have.property('imsi');
        res.body.should.have.property('probe_name');
        res.body.should.have.property('msisdn');
        setTimeout(function() {
          done();
        }, 1000);
      });
  });


  it('Sim imsi/msisdn is unique in the database', function(done){
    var newSim = {
      msisdn:     '1234',
      imsi:       '007',
      probe_name: 'BOUCHON_1'
    };

    request(this.server)
      .post('/sims')
      .set('Content-Type', 'application/json')
      .send(newSim)
      .expect(200).end(function(err, res) {
        if (err) return done(err);
        res.body.should.have.property('error').equal('Duplicate Item');
        done();
      });
  });


  after(function(done) {
    app.stop(done);
  });
});

如果我直接运行它,它就工作正常:

julio$ mocha test/controllers/ctrl_sim.js 

但是如果我使用隐性选项运行它,它会失败:

  1) [ Sim controller ]  Sim imsi/msisdn is unique in the database:
     Uncaught AssertionError: expected { __v: 0,
  imsi: '007',
  msisdn: '1234',
  probe_name: 'BOUCHON_1',
  _id: '530a2b7f52273aa90783baf0',
  status: true } to have property 'error'

我在stackoverflow上看到过,有时由于索引未刷新,unique条件不能得到很好的满足。您认为这是我的情况吗?事实上,我会在每个mocha测试套件中删除数据库。也许Mongo没有时间在每次重新创建所有索引。

您有什么想法?

1个回答

98

使用dropDups可以确保在模式中删除重复记录,例如:

var SimSchema = new Schema({
    msisdn     : { type : String , unique : true, required : true, dropDups: true },
    imsi       : { type : String , unique : true, required : true, dropDups: true },
    status     : { type : Boolean, default: true},
    signal     : { type : Number },
    probe_name : { type:  String , required : true }
});

在运行测试之前,请重新启动mongodb。


9
我不理解dropDups的用途,您能否详细解释一下?dropDups是用来移除重复值的。 - Vikas Bansal
4
如果将dropDups设置为true,MongoDB会删除之前创建的重复项。 - Hasaan Ali
11
不完全正确- dropDups 意味着 MongoDB 将“删除”任何试图使用数据库中已存在的架构值创建记录的查询。例如:如果你已经有一个 name:bob 的记录,然后你尝试插入另一条 name:bob 的记录,那么由于 dropDups,此插入将失败。 - Janac Meena
3
如果你在使用 mongoose,我认为 email: {type: String, unique: true} 可能无法正常工作。虽然我没有测试过,但可能是这样的:如果你的数据值已经存在,那么如果添加键 unique: true,它将不起作用。(如果没有数据,则未检查)。你应该在 MongoDB shell 中创建索引,然后再使用 mongoose。你可以参考我的另一个答案:https://dev59.com/qWEh5IYBdhLWcg3wRRqh#56302405 - William Hu
2
@WilliamHu 是的,只要索引在文档插入之前创建就可以了。mongoose 文档将其称为“竞争” :P https://mongoosejs.com/docs/validation.html#the-unique-option-is-not-a-validator因此,当我设置 dropDups 时,无论是先保存还是先创建索引,其中一个 dropDupsunique 就会起作用。完成工作 :) - Rishav
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接