gpt4 book ai didi

javascript - MongoDB 重复键错误

转载 作者:行者123 更新时间:2023-11-30 21:06:07 26 4
gpt4 key购买 nike

所以现在,我正在开发一项服务,允许多个事件在 MongoDB 上存储数据。每次出现新事件时,它们都会通过在 MongoDB 上创建新集合来存储事件数据。如果同一事件需要存储不同的数据集,则应在 MongoDB 中创建一个新文档。

下面的代码是我创建的用于处理此问题的服务。

import WhiteBoardEvent from '../model/event.model';
import IEventStore from '../interface/eventStore.interface';
import * as MongoClient from 'mongodb';

export class EventStore implements IEventStore {
private mongoDBEndpoint = "mongodb://192.168.10.10:27017";


public insert(event: WhiteBoardEvent, callback: (err: any) => void): void {
MongoClient.connect(this.mongoDBEndpoint, { connectTimeoutMS: 1000 }, (connErr, db) => {
if (connErr) { db.close(); callback(connErr); return; }
this.getNextSequence(db, event, (err, sequence) => {
if (err) { db.close(); callback(err); return; }
event.sequence = sequence;
db.collection(event.roomId).insert(event, (err) => {
db.close();
callback(err);
});
});
});
}

private createCounterCollection(db: MongoClient.Db, event: WhiteBoardEvent, callback: (err: any) => void): void {
db.collection("counters").insert({
roomId: event.roomId,
sequence: 0
}, callback);
}

private getNextSequence(db: MongoClient.Db, event: WhiteBoardEvent, callback: (err: any, sequence: number) => void): void {
var collection = db.collection("counters");
collection.findOneAndUpdate(
{ roomID: event.roomId },
{
$inc: { sequence: 1 },
// new: true
},
{
upsert: true,
returnOriginal: false
},
(err, r) => {
if (err) {
this.createCounterCollection(db, event, (err) => {
if (err) { callback(err, -1); return; }
callback(null, 0);
});
return;
}
callback(null, r.value.sequence);
console.log("counter : " + r.value.sequence);
}
);
}
}

下面的代码是我创建的一个测试文件,这样我就可以看到MongoDB中的变化。

import * as timers from 'timers';
import WhiteBoardEvent from './data/model/event.model';
import { EventStore } from './data/service/eventStore.service';

var model = new WhiteBoardEvent();
model.name = "t2";
model.roomId = "testRoom";
model.timestamp = new Date();
model.userId = "";


var model2 = new WhiteBoardEvent();
model2.name = "t1";
model2.roomId = "testRoom2";
model2.timestamp = new Date();
model2.userId = "";

var eventStore = new EventStore();

var timer1 = timers.setInterval(()=>{
eventStore.insert(model, (err)=>{
if(err){
console.log(err);
}else{
console.log("Test Completed!");

}
});
}, 1000);

var timer2 = timers.setInterval(()=>{
eventStore.insert(model2, (err)=>{
if(err){
console.log(err);
}else{
console.log("Test Completed!");

}
});
}, 1000);

这是我得到的输出的一个片段。此处,第一个实例显示“测试已完成”,之后,我收到重复错误。

counter : 1
counter : 1
Test Completed!
Test Completed!
counter : 2
{ MongoError: E11000 duplicate key error collection: admin.testRoom index:
_id_ dup key: { : ObjectId('59d5da14cedd6f28a5db8c93') }

谁能帮我解决这个问题?先感谢您!

最佳答案

您正在创建 WhiteBoardEvent 的两个实例,但没有明确设置 ID(这很好,但很重要)。看看上面代码的摘录:

db.collection(event.roomId).insert(event, (err) => {
db.close();
callback(err);
});

event 交给 MongoDB 的 insert 后,检查它是否有 ID - 它没有。因此,MongoDB 代码会为您生成一个 ID(请参阅 here)。这一切都很棒 - 这就是您想要的。

但是,下一次 setInterval 回调被调用时会发生什么?嗯,modelmodel2 现在有一个 ID 集——它是根据我刚才描述的规则设置的。在这种情况下,既然在 model 上设置了一个 ID 进入 insert,您将尝试重用相同的 ID,因为 MongoDB 代码不理会它。

在您的测试代码中,您可以简单地清除 eventStore.insert 回调中的 ID,以确保每次都生成一个新 ID。例如:

eventStore.insert(model, (err)=>{
model._id = null;

if(err){
console.log(err);
}else{
console.log("Test Completed!");
}
});

关于javascript - MongoDB 重复键错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46579968/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com