【问题标题】:Find, if not exists, insert, vulenrability查找,如果不存在,插入,漏洞
【发布时间】:2019-11-06 11:02:45
【问题描述】:

执行>10个请求,至少,同时,这段代码插入4条相同的记录,但必须只插入1条。

用户只能开始 1 个活动游戏。 (在活跃游戏领域finished = false

console.log('performing request');
const activeGame = await db.Game.findOne({ uid, finished: false });
if (activeGame !== null) {
    console.log('errored');
    return { error: 'Finish previous game.' };
} else {
    console.log('inserted');
    const game = new db.Game({
        uid,
        moves: new Array(5*5).fill(0)
    });
    game.save();
    return game;
}

同时记录 10 个请求:

performing request
inserted
performing request
performing request
inserted
performing request
inserted
inserted
performing request
errored
performing request
errored
performing request
errored
performing request
errored
performing request
performing request
errored
errored

事务对我没有帮助。

【问题讨论】:

    标签: javascript node.js mongodb mongoose fastify


    【解决方案1】:

    当然,这段代码很容易出现竞争条件。为避免这种情况,您可以使用 All you need is a partial unique index。将其应用于 uid 字段的文档,其中 finished: false 等等,您现在无法为同一用户插入两个活动游戏。

    【讨论】:

    • 插入时如何使用?
    • @koljacheesch:文档中有示例。寻找upsert 选项
    • 我已经看过这一篇了,但是我不明白如何插入,使用这个功能。我还在这个问题中写了一小部分代码,activeGame 发现发生在其他地方(在中间件中),但插入发生在 game.js 中。另外我不知道如何拆分此功能。如果执行相同的代码会破坏项目结构...
    • @koljacheesch:如果我今天晚些时候有时间,我会尝试做一个例子。至于您的其他问题(查找和更新发生在不同的地方):maaaaybe 您可以通过创造性地应用唯一索引来解决它。但您更有可能不得不重新考虑这种设计。
    • 谢谢。好吧,我需要一点其他逻辑,我根本不需要更新,我需要 findOneAndInsert,而不是 findOneAndUpdate...
    【解决方案2】:

    您的 uid 不同,因此它会插入这些时间。如果您将传递相同的 uid,那么它将根据您的需要工作。

    你可以试试这些。并读取 save() 功能。

    console.log('performing request');
    const activeGame = await db.Game.findOne({ _id: uid, finished: false });
    if (activeGame == null) {
          console.log('inserted');
        const game = new db.Game({
            moves: new Array(5*5).fill(0)
        });
        game.save();
        return game;
    } else {
        console.log('errored');
        return { error: 'Finish previous game.' };
    }
    

    console.log('performing request');
    const activeGame = await db.Game.findOne({ _id: uid, finished: false });
    activeGame.save()
    

    【讨论】:

    • 您是如何推断出 uid 会有所不同的?另外,为什么您认为它不仅仅是一个常规字段?
    • 我的uid是一样的。我正在传递相同的 uid 变量。
    • 如果它不是常规字段,那么为什么要在 save() 中更新它
    • 不,uid 不能是唯一的_id。用户可能有很多已完成的游戏。但活跃游戏只有一个。
    猜你喜欢
    • 2022-11-29
    • 2020-11-25
    • 2017-04-24
    • 1970-01-01
    • 2011-09-14
    • 2016-01-06
    • 1970-01-01
    • 2018-09-17
    相关资源
    最近更新 更多