Javascript 如何对mongodb文档进行原子自定义更新?

Javascript 如何对mongodb文档进行原子自定义更新?,javascript,mongodb,transactions,Javascript,Mongodb,Transactions,我知道MongoDB可以使用findOneAndModify进行原子更新,但这只允许像set或increment这样的基本操作 我需要的是应用自定义函数来转换我的文档: const updateDoc = async (event) => { const oldState = await db.collection(collectionName).findOne({ name }); const newState = customFunction(oldState, event);

我知道MongoDB可以使用findOneAndModify进行原子更新,但这只允许像set或increment这样的基本操作

我需要的是应用自定义函数来转换我的文档:

const updateDoc = async (event) => {
  const oldState = await db.collection(collectionName).findOne({ name });
  const newState = customFunction(oldState, event);
  await db.collection(collectionName).replaceOne({ name }, newState);
}
此函数将由一个系统调用,该系统不会等待已解决的承诺继续工作:可以有多个同步调用

有没有办法重写updateDoc以使其原子化,这样当我们这样做时:

updateDoc(event1); // note the absence of await
updateDoc(event2);
我们可以确定存储的文档将是CustomFunctionCustomInitState、event1、event2


谢谢

一个可能的解决方案是任务队列,它安排一个又一个更新:

class Scheduler {
  constructor(){
    this.running = false;
    this.queue = [];
  }

  add(el){
     this.queue.push(el);
     if(!this.running) this.run();
  }

  async run(){
    this.running = true;
    while(this.queue.length) await this.queue.shift();
    this.running = false;
 }
}
可以这样使用:

 const dbTasks = new Sheduler();

 const updateDoc = async (event) => dbTasks.add( _ => {
   const oldState = await db.collection(collectionName).findOne({ name });
   const newState = customFunction(oldState, event);
   await db.collection(collectionName).replaceOne({ name }, newState);
});

updateDoc(evt1);
updateDoc(evt2);

如果您担心oldState是您决定使用的newState,但在编写newState时,oldState实际上可能不是数据库中当前的状态,在您做出决定时,它可能实际上不是数据库中的状态。以下可能会有所帮助:根据您需要扩展的大小,您可能希望使用事件存储进行CQR,您从不更新事件,而是使用它们来计算当前状态,并且数据最终是一致的。谢谢。我实际上在做CQRS+事件存储,我读过存储在mongodb中并在新事件上重新编写的投影,这个问题是关于这些投影的:如果Thomas concern是脏读?那么这会有帮助吗?看起来他想获取数据,根据获取的数据决定新数据,保存新数据。在获取数据和保存数据之间的某个地方,mongodb可以刷新对该特定文档的某些更改。@据我所知,问题是当前它的get-event1->get-event2->set-event1->set-event2不考虑event1的更改。使用队列解决了这一问题我对mongo了解不够,但不确定“已解决的写入承诺”是否意味着,当您在任务队列中读取它之后立即读取时,您实际上得到了刚刚写入的数据,尤其是在为写入而聚集和优化时。根据OP的需要,序列化所有db读/写可能不能很好地扩展,但确实满足了他的要求。@hmr我不是mongodb专家。你的观点可能是对的,但我说不准