当 id 字段与对象中的 id 字段匹配时,通过将对象推送到数组字段来更新许多文档

问题描述 投票:0回答:1

好吧,这个问题听起来不太清楚。我会尽力解释。 我有一个 F1 车手集合,其中包含一个数组字段来存储每场比赛获得的积分。 我使用 Web 表单提交给定比赛的完整结果,其中包含 race_id、race_name 和位置数组,其中包含 driver_id 和作为每个车手的对象获得的积分。 我现在需要通过将驱动程序 ID 与对象数组中的 ID 进行匹配,用本次比赛的结果更新集合中的每个驱动程序。 最终;我还需要更新每个司机的总积分,但现在可以等待。

// The handler for my web form
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);
}

// Post result to the endpoint
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));
}

//My endpoint and Mongoose query
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);
    })
})

// The model
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 };
mongodb express mongoose push insert-update
1个回答
0
投票

为了让您大致了解如何解决此问题,我在 mongoplayground 中准备了一个示例,该示例展示了如何使用聚合管道的更新来执行文档的复杂更新。假设您的收藏中有 3 名车手,分别为

_id
1、2 和 3。车手 1 和 2 已经在第一场比赛中获得了一些积分,而车手 3 到目前为止还没有任何成绩。

在下一场比赛中,车手 1 和 3 都获得了积分,因此这两位车手应该更新,以便

  1. 如果
    results
    字段尚不存在,则将其初始化为空数组,
  2. 新授予的积分应添加到
    results
    数组中,
  3. 驱动程序
    _id
    已从
    results
    字段中删除并且
  4. total
    字段应更新为总点数。

该示例假设有一个包含应更新驱动程序

_id
的数组 (
[1, 3]
),还有一个包含结果的数组:

  [
    {
      _id: 1,
      race_id: 2,
      race_name: "Spa",
      points: 7
    },
    {
      _id: 3,
      race_id: 2,
      race_name: "Spa",
      points: 3
    }
  ]

以下更新语句用于执行更新:

db.collection.update({
  _id: {
    $in: [
      1,
      3
    ]
  }
},
[
  {
    $set: {
      results: {
        $ifNull: [
          "$results",
          []
        ]
      }
    }
  },
  {
    $set: {
      results: {
        $concatArrays: [
          "$results",
          {
            $filter: {
              input: [
                {
                  _id: 1,
                  race_id: 2,
                  race_name: "Spa",
                  points: 7
                },
                {
                  _id: 3,
                  race_id: 2,
                  race_name: "Spa",
                  points: 3
                }
              ],
              cond: {
                $eq: [
                  "$$this._id",
                  "$_id"
                ]
              }
            }
          }
        ]
      }
    }
  },
  {
    $unset: "results._id"
  },
  {
    $set: {
      total: {
        $sum: "$results.points"
      }
    }
  }
],
{
  multi: true
})

请使用此示例作为起点,您可以将其集成到您的猫鼬环境中。

© www.soinside.com 2019 - 2024. All rights reserved.