使用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
相关产品推荐
相关产品推荐

