匹配ID批量更新MongoDB文档:向数组字段推送赛事成绩对象
问题描述
我在MongoDB中维护了一个F1车手集合,集合内文档包含id、driver_name、totla_points(注:此处为拼写错误)以及用于存储各赛事积分的results数组字段。通过网页表单提交单场赛事的完整结果,表单数据包含event_id、event_name,以及由多个含driver_id和对应积分的对象组成的positions数组。
需求:根据车手id与positions数组中对象的id匹配,批量更新集合中对应车手的文档,将该赛事的成绩(event_id、event_name、points)推送至其results数组中。后续还需更新车手的total_points字段(当前暂不处理)。
当前使用updateMany查询无法正确实现需求,请求修正代码。
现有代码
前端表单处理与提交代码
// 网页表单处理函数 function handleRaceResultSubmit(e) { e.preventDefault(); let positions = [{id: null, points: 25}, {id: null, points: 18},{id: null, points: 15},{id: null, points: 12},{id: null, points: 10}, {id: null, points: 8},{id: null, points: 6},{id: null, points: 4},{id: null, points: 2},{id: null, points: 1}, {id: null, points: 0},{id: null, points: 0},{id: null, points: 0},{id: null, points: 0},{id: null, points: 0}, {id: null, points: 0},{id: null, points: 0},{id: null, points: 0},{id: null, points: 0},{id: null, points: 0},]; const eventID = parseInt(document.querySelector('#event-select').value); const eventName = document.querySelector('#event-select').textContent; const selectGroup = document.querySelectorAll('.select-group'); selectGroup.forEach((driver, index) => { positions[index].id = parseInt(driver.value); }) const raceResult = { event_id: eventID, event_name: eventName, result: positions } updateDriverResults(raceResult); } // 向接口提交结果 const updateDriverResults = async (data) => { fetch('driver-points', { method: "POST", headers: {"Content-Type": "application/json"}, body: JSON.stringify(data) }).then(res => {return res.json()}) .then(data => console.log(data)) .catch(error => console.log(error)); }
后端接口与Mongoose查询代码
// 后端接口及Mongoose查询 app.post('/driver-points', express.json(), (req, res) => { Drivers.updateMany({ 'id': { $in: [ req.body.result.id ] }, }, { $push: {'results': { 'event_id': req.body.event_id, 'event_name': req.body.event_name, 'points': req.body.result.points }} }) .then((result) => { res.send(result); }) .catch((error) => { console.log(error); }) })
Mongoose模型代码
// Mongoose模型 import { mongoose } from "mongoose"; const Schema = mongoose.Schema; const driversSchema = new Schema({ id: Number, driver_name: String, totla_points: Number, results: Array }); const Drivers = mongoose.model('driver', driversSchema); export { Drivers };
问题分析与修正方案
当前updateMany查询的核心问题:
req.body.result是数组,req.body.result.id返回undefined,导致$in条件无效,无法匹配任何车手idupdateMany无法为不同文档设置不同的更新值,所有匹配车手会被推送相同积分,不符合需求
正确实现需使用批量写入(bulkWrite),遍历positions数组为每个车手生成独立更新操作:
修正后的后端接口代码
app.post('/driver-points', express.json(), async (req, res) => { try { const { event_id, event_name, result: positions } = req.body; // 过滤id为null的无效条目 const validPositions = positions.filter(pos => pos.id !== null); const bulkOps = validPositions.map(pos => ({ updateOne: { filter: { id: pos.id }, update: { $push: { results: { event_id, event_name, points: pos.points } // 后续更新total_points时,添加以下代码: // $inc: { total_points: pos.points } } } } })); const result = await Drivers.bulkWrite(bulkOps); res.send(result); } catch (error) { console.error(error); res.status(500).send({ error: '更新失败' }); } })
额外优化建议
- 修正模型中
totla_points的拼写错误为total_points,避免维护混淆 - 为
results字段定义明确Schema结构,提升数据一致性:
const driversSchema = new Schema({ id: Number, driver_name: String, total_points: Number, // 修正拼写错误 results: [{ event_id: Number, event_name: String, points: Number }] });
内容的提问来源于stack exchange,提问作者Mark McNaughton
相关产品推荐
相关产品推荐

