防止猫鼬中的重复记录

Cod*_*ely 11 javascript mongoose mongodb mongoose-schema

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

我有一个相当简单的事件架构。

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 },
});
Run Code Online (Sandbox Code Playgroud)

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

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

我编写了一个测试,检查是否不应该插入具有相同 pkey 的记录,以及 unique:true 是否正在运行。我已经有一组我读入数组的事件,所以我只是再次发布这些事件中的第一个,看看会发生什么,我预计 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); 
   }); 
Run Code Online (Sandbox Code Playgroud)

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

当我查看集合时,我可以看到两条记录,它们都具有相同的 pkey(原始记录和我为测试发布的副本)。我确实注意到第二条记录的创建日期与第一条记录的创建日期相同,但修改日期较晚。

(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' }
]
Run Code Online (Sandbox Code Playgroud)

我曾假设唯一的:字段定义中的 true 告诉 mongo db 这是您想要的,并且 mongo 在保存时为您强制执行,或者我可能只是误解了一些东西......

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

/events/1
Run Code Online (Sandbox Code Playgroud)

而不是一团糟的复合值,比如

/events/Event%20name%2001%5fDevice%20X%5fTest%20Owner
Run Code Online (Sandbox Code Playgroud)

我正要开始编写代码,所以现在我只是针对这个字符串编写了一个简单的测试,但真正的模式有更多的字段,并将使用它们的组合来实现唯一性,我真的很想获得初始值在我开始添加更多测试、更多字段和更多代码之前测试工作。

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

Siy*_*lav 6

在数据库中插入一些记录后,您似乎已经完成了唯一索引(在架构级别)。

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

1)删除你的数据库:

$ 蒙戈

> use <db-name>;

> db.dropDatabase();
Run Code Online (Sandbox Code Playgroud)

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 },
    });
Run Code Online (Sandbox Code Playgroud)

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

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

我希望它有帮助。谢谢


Cod*_*ely 1

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

  • 需要对等待“索引”的插入做一些事情
  • 需要是 API 端,因为并非所有 API 用户都是 Web 应用程序

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

猫鼬独特:真的不行

唯一索引不适用于 Mongoose / MongoDB

MongoDB/Mongoose 对日期字段的唯一约束