2

I have this updateGameScore asynchronous service function, which is used to add new record if there's no record already in the GameScore collection with the perticular user ID, or update relevant record if exists:

const updateGameScore = async (userId, gameId, score, date, res) => {

    const gameScore = await GameScore.findOne({ userId });

    //If no record found with given userId, a new record will be created
    if (!gameScore) {
        let newGameScore = new GameScore({
            userId,
            gameScores: { gameId, highScore: score },
            totalScore: score,
            date,
        });

        newGameScore = await newGameScore.save();
    }
    //If there is already a record of the given userID
    else {
        //The totalscore field of that user will be updated by adding the new score to the current total score
        const totalScore = gameScore.totalScore + score;
        await GameScore.findByIdAndUpdate(
            { _id: gameScore._id },
            { totalScore, date }
        );
    }

And then I call this function within a map function to make 50,000 calls from a db collection that already exist.

    allPlayers = await Player.find();
    await allPlayers.map((player) => {
        const userId = player.userId;
        const gameId = player.gameId;
        const score = player.score;
        const date = player.date;

        updateGameScore(userId, gameId, score, date, res);
    });

However my code, the updateGameScore function works properly(if I call it one by one). but when I call 50,000 records at once, all records call this function parallelly, and makes 50,000 new records on my GameScore collection, which I do not need to happen. I just need to create new record if a record with the given userId doesn't exist but update the record if a record with given ID exist. This would work properly if my map function call the updateGameScore function sequntially, but unfortunately it does not. Please help me with this as I have very poor knowledge in asynchronous js.

  • 2
    Correct me if I'm wrong but if the upsert process is ID based, why would it make a difference? Shouldn't all 50.000 players have a unique ID? –  Sep 16 '21 at 07:17
  • @ChrisG - Yeah. I didn't look too closely at the source of the array so I assumed there could be more than one instance of a given `userId` in it. But looking, it's coming from `Player.find`, which -- as you say -- would presumably return objects with unique `userId`s. So I'm not getting that part either. – T.J. Crowder Sep 16 '21 at 07:49
  • It sounds like you want to make your calls in series rather than in parallel; see the linked question's answers. Basically, use a `for` or `for-of` loop and `await`: ```for (const {userId, gameId, score, date} of allPlayers) { await updateGameScore(userId, gameId, score, date, res); }``` `updateGameScore` returns a promise *(all async functions do)* and it awaits the various updates it does, so its promise won't settle until those updates are complete. That means we can use `await` in the loop to wait until that promise settles before continuing with the next player. – T.J. Crowder Sep 16 '21 at 07:58

0 Answers0