防止Mongoose中的重复记录

时间:2016-03-23 08:16:48

标签: javascript mongodb mongoose mongoose-schema

我对MongoDb / Mongoose相当新,更习惯于SQL Server或Oracle。

我对事件有一个相当简单的Schema。

EventSchema.add({
  pkey: { type: String, unique: true },
  device: { type: String, required: true },
  name: { type: String, required: true },
  owner: { type: String, required: true },
  description: { type: String, required: true },
});

我在看Mongoose Indexes,它显示了两种方法,我使用了字段定义。

我还有一个非常简单的API,它接受POST并在此集合上调用create来插入记录。

我编写了一个测试,检查是否应该插入具有相同pkey的记录,并且唯一:true正在运行。我已经有一组事件,我读入一个数组,所以我只是再次POST这些事件中的第一个,看看会发生什么,我预计mongo DB会抛出E11000重复键错误,但这没有发生。

var url = 'api/events';
var evt = JSON.parse(JSON.stringify(events[0]));

// POST'ed new record won't have an _id yet 
delete evt._id;

api.post(url)
   .send(evt)
   .end(err, res) {
     err.should.exist; 
     err.code.should.equal(11000); 
   }); 

测试失败,没有错误,插入了重复记录。

当我看一下这个集合时,我可以看到两个记录,两个记录都有相同的密钥(原始记录和我为测试发布的副本)。我注意到第二条记录的创建日期与第一条记录的创建日期相同,但后来的修改日期相同。

(mongo希望我使用最新的修改版本记录???,URL不同,ID也是如此)

[ { _id: 2,
    pkey: '6fea271282eb01467020ce70b5775319',
    name: 'Event name 01',
    owner: 'Test Owner',
    device: 'Device X',
    description: 'I have no idea what\'s happening',
    __v: 0,
    url: '/api/events/2',
    modified: '2016-03-23T07:31:18.529Z',
    created: '2016-03-23T07:31:18.470Z' },
  { _id: 1,
    pkey: '6fea271282eb01467020ce70b5775319',
    name: 'Event name 01',
    owner: 'Test Owner',
    device: 'Device X',
    description: 'I have no idea what\'s happening',
    __v: 0,
    url: '/api/events/1',
    modified: '2016-03-23T07:31:18.470Z',
    created: '2016-03-23T07:31:18.470Z' }
]

我认为这是唯一的:真正的字段定义告诉mongo db这是你想要的,mongo在保存时为你强制执行,或者我只是误解了一些东西......

在SQL术语中,您创建了一个可用于URL查找的键,但您可以构建唯一的复合索引,以防止重复插入。我需要能够定义事件中的哪些字段使记录唯一,因为在表单数据POST上,表单的提交者没有下一个可用的_id值,但使用_id(由" mongoose-auto完成) -increment")以便从应用程序的其他部分使用URL是干净的,例如

/events/1

并不是一堆完整的复合值,比如

/events/Event%20name%2001%5fDevice%20X%5fTest%20Owner

我即将开始编码所以现在我只是针对这个单字符串编写了一个简单的测试,但是真正的模式还有一些字段,并且将它们的组合用于唯一性,我真的我想在开始添加更多测试,更多字段和更多代码之前进行初始测试。

我应该做些什么来确保第二条记录实际上没有插入?

5 个答案:

答案 0 :(得分:2)

在 mongoose.connect 添加 {useCreateIndex: true}

应该是这样的

mongoose.connect(uri, {
useNewUrlParser: true, 
useUnifiedTopology: true, 
useCreateIndex: true
})

答案 1 :(得分:0)

添加:

EventSchema.index({ pkey: 1 }, { unique: true });

答案 2 :(得分:0)

好的,看起来它与索引没有时间在第二次插入发布之前更新有关(因为我的测试套件中它们之间只有9ms)。

  • 需要对等待" index"
  • 的插入执行某些操作
  • 需要是API方面,因为并非API的所有用户都是Web应用程序

我还发现了一些关于约束的其他SO文章:

mongoose unique: true not work

Unique index not working with Mongoose / MongoDB

MongoDB/Mongoose unique constraint on Date field

答案 3 :(得分:0)

我似乎在db。中插入一些记录后,已经完成了独特的索引(在模式级别)。

请按照以下步骤避免重复 -

1)放弃你的数据库:

$ mongo

> use <db-name>;

> db.dropDatabase();

2)现在在架构级别或数据库级别进行索引

 var EventSchema = new mongoose.Schema({
      pkey: { type: String, unique: true },
      device: { type: String, required: true },
      name: { type: String, required: true },
      owner: { type: String, required: true },
      description: { type: String, required: true },
    });

它将避免使用相同的pKey值插入重复记录。

并且为了确保索引,请使用命令db.db_name.getIndexes()

希望这会有所帮助。

答案 4 :(得分:0)

// Rebuild all indexes
await User.syncIndexes();

为我工作。 来自https://masteringjs.io/tutorials/mongoose/unique