You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Mongoose操作MongoDB时无法避免子文档数组重复问题

MongoDB子文档数组更新/添加时出现重复项问题

需求说明

需要根据price_level字段的值,对MongoDB子文档数组entries中的对象执行更新或添加操作:

  • 若entries中存在指定price_level的对象,更新其volume为新值
  • 若不存在,将新元素{ price_level, volume }添加到数组中

数据Schema定义

import mongoose, { Schema } from 'mongoose';

const orderBookSchema = new Schema({
   pair_name: {
      type: String,
      required: true
   },
   side: String,
   entries: [{ price_level: String, volume: String }],
});

export const OrderBook = mongoose.model('OrderBook', orderBookSchema);

实现代码

static updateOrderBook = async (pairName: string, side: 'ask' | 'bid', orderBookEntries: string[][], deleteExisting: boolean = false) => {
   const existingOrderBook = await OrderBook.findOne({ pair_name: pairName, side });

   if (!existingOrderBook) {
      await OrderBook.create({ pair_name: pairName, side, entries: [] });
   }

   if (deleteExisting) {
      const filter = { pair_name: pairName, side };
      const update = { $set: { entries: [] } };
      await OrderBook.updateOne(filter, update).exec();
   }

   for await (const [priceLevel, volume] of orderBookEntries) {
      const filter = {
         pair_name: pairName,
         side,
         'entries.price_level': priceLevel
      };

      const update = { $set: { 'entries.$.volume': volume } };
      const result = await OrderBook.updateOne(filter, update).exec();

      if (result.matchedCount === 0) {
         const newElement = { price_level: priceLevel, volume: volume };
         const addUpdate = { $addToSet: { entries: newElement } };
         await OrderBook.updateOne({ pair_name: pairName, side }, addUpdate).exec();
      }
   }

   const filter = { pair_name: pairName, 'entries.volume': '0.00000000' };
   const update = { $pull: { entries: { volume: '0.00000000' } } };
   await OrderBook.updateOne(filter, update).exec();
};

问题现象

手动测试硬编码数据时功能正常,但从Kraken WebSocket API获取数据时,偶尔会出现entries数组中存在相同price_level的重复对象,示例如下:

entries: [
    // ...更多元素
    {
      price_level: '23463.40000',
      volume: '0.13447916',
      _id: new ObjectId("6401151cc708de7a1ff9bf01")
    },
    {
      price_level: '23463.40000',
      volume: '0.13447916',
      _id: new ObjectId("6401151cc708de7a1ff9c0ac")
    }
    // ...更多元素
]

已尝试的解决方法

  • 将子文档的price_level和volume属性改为Number类型
  • 添加事务处理
  • 移除数据库复制配置
  • 去掉.exec()调用
    以上操作均未解决重复项问题。当前使用环境:MongoDB Community 6.0、mongoose 6.9.0

疑问

我的查询逻辑是否存在错误?


内容的提问来源于stack exchange,提问作者serlingpa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:27:04