【问题标题】:Preventing duplicate records in Mongoose防止 Mongoose 中的重复记录
【发布时间】:2016-07-10 10:22:32
【问题描述】:

我对 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 },
});

我正在查看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); 
   }); 

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

当我查看集合时,我可以看到两条记录,它们都具有相同的 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' }
]

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

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

/events/1

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

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

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

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

【问题讨论】:

  • 去读一些东西,不是很有帮助......,我包括了“mongoose-auto-increment”,它显然会创建_id,并让它们在每次保存时增加 1。 _id 对于 /events/:id 可能是唯一且有用的,但这并不是使记录唯一的原因,这是由事件(待添加)字段的复合组合决定的。在我开始向索引添加多个值并对整个事物进行编码之前,我想看看它是否可以对架构的一个字段进行更简单的测试。复合键值在 URL 中给出 event/{:horible_key}

标签: javascript mongodb mongoose mongoose-schema


【解决方案1】:
// Rebuild all indexes
await User.syncIndexes();

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

【讨论】:

    【解决方案2】:

    在 mongoose.connect 上添加 {useCreateIndex: true}

    应该是这样的

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

    【讨论】:

      【解决方案3】:

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

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

      1) 删除你的数据库:

      $ 蒙戈

      > 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】:

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

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

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

        mongoose unique: true not work

        Unique index not working with Mongoose / MongoDB

        MongoDB/Mongoose unique constraint on Date field

        【讨论】:

          【解决方案5】:

          添加:

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

          【讨论】:

          • 好的 - 我这样做了,但结果是一样的,我得到了两条插入了相同 pkey 值的记录...作为快速测试,我也尝试了你的建议,并从字段定义中删除了唯一性好吧(不确定您是否要我替换它),但这也会插入两条记录... :(
          猜你喜欢
          • 2015-12-04
          • 1970-01-01
          • 2015-08-23
          • 1970-01-01
          • 1970-01-01
          • 2016-12-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多