MERN Stack:如何防止用户多次注册(添加到数组中)?

MERN Stack: How to prevent a User from registering (being added to an array) multiple times?

半新开发人员使用 MERN 堆栈构建项目。

该应用有两种型号,一种用于 Users,一种用于 Tournaments。锦标赛模型有一个名为 participants 的属性,它是一个数组。

我编写了一个 Express 后端路由,以便用户可以注册 Tournaments.participants[]。 这看起来像:

router.post('/:id', (req, res) => {
    Tournament.findById(req.params.id)
        .then(tournament => {
            tournament.participants.push(req.body);
            return tournament.save();
        })
        .then(savedTournament => res.json(savedTournament))
        .catch(err => res.json(err));
});

但是,用户可以一直点击“注册”,我会有一堆重复的用户,所以我正在尝试编写一个条件,如果用户已经在 Tournament.participants[].

我尝试使用 Array.includes(req.body) 在 Express 路由中编写条件,但无法破解它。 看起来像

Tournament.findById(req.params.id)
        .then(tournament => {
            if (tournament.participants.includes(req.body) {
              return res.status(400).json({ msg: "This user already signed up for this tournament" });
            } else {
              tournament.participants.push(req.body);
              return tournament.save();
            }
        })
        .then(savedTournament => res.json(savedTournament))
        .catch(err => res.json(err));

我也尝试了不同的变体,比如 if (tournament.participants.includes(!req.body)) 然后 push(req.body) 等等

如果 participants.includes(user) 我也尝试过渲染一个不同的按钮,但我相信这应该在后端完成。我愿意接受建议。

谁能帮帮我?

一般来说,您不能对对象使用本机比较运算符,includes包括:

const foo = { id: 1 };
const bar = [{ id: 1 }];
console.log(bar.includes(foo)); // outputs `false`

您应该使用某种项目 id 来检查它是否已经存在:

function isIdIncluded(arr, id) {
  return arr.some(x => x.id === id) 
}

const foo = { id: 1 };
const bar = [{ id: 1 }];
console.log(isIdIncluded(bar, 1)); // outputs `true`

我假设您将用户的 _id 保存在 participants 数组中,并且您的锦标赛架构类似于:

const tournamentSchema = new mongoose.Schema({
  name: String,
  participants: Array,
});

现在,如果您发送带有此正文的请求:

{
    "user": "5e97255a342f395774f30162"  //the user id who wants to participate
}

您可以使用此代码(我只是将 req.body 更改为 req.body.user

  Tournament.findById(req.params.id)
    .then((tournament) => {
      if (tournament.participants.includes(req.body.user)) {
        return res.status(400).json({ msg: "This user already signed up for this tournament" });
      } else {
        tournament.participants.push(req.body.user);
        return tournament.save();
      }
    })
    .then((savedTournament) => res.json(savedTournament))
    .catch((err) => res.status(500).json(err));

现在当用户第一次参加比赛时,文档将是这样的:

{
    "participants": [
        "5e97255a342f395774f30162"
    ],
    "_id": "5e97255a342f395774f30161",
    "name": "Chess Tournament"
}

当同一个用户尝试时,响应将是这样的,带有 400 状态代码。

{
    "msg": "This user already signed up for this tournament"
}

另请注意,用户id不应该在请求正文中发送,但必须是登录用户的id。