You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongo更新文档时触发E11000重复键错误,求排查方案

解决MongoDB E11000重复键错误(voters字段)

错误原因

你遇到的E11000 duplicate key error,是因为MongoDB的elections集合中,voters字段被创建了唯一索引(索引名voters_1)。你的代码逻辑是用$push往voters数组里添加已投票用户名,当同一个用户再次投票时,就会触发唯一索引的重复校验,抛出错误。

注意:你的Mongoose Schema里并没有给voters定义唯一约束,这个索引应该是之前手动在MongoDB中创建,或其他操作误添加的。


解决方案

步骤1:删除多余的唯一索引

连接MongoDB,执行以下命令删除voters字段的唯一索引:

db.elections.dropIndex("voters_1")

步骤2:添加投票重复校验逻辑

在修改文档前,先检查用户是否已投票,避免重复操作;同时用原子操作优化投票计数逻辑,避免竞态条件。

修改后的后端代码

import connectDb from "@/middleware/db";
import Election from "@/models/Election";
const jwt = require("jsonwebtoken");

const Vote = async (req, res) => {
    try {
        await connectDb();

        // 验证JWT token
        const u = jwt.verify(req.body.token, "!stackoverflow!");
        const username = u.username;
        const electionSlug = req.body.slug;
        const candidateIndex = req.body.i;

        // 检查用户是否未投票,同时获取选举数据
        const election = await Election.findOne({
            election_name: electionSlug,
            voters: { $ne: username }
        });

        if (!election) {
            return res.json({ success: false, message: "用户已投票或选举不存在" });
        }

        // 原子更新:自增候选人票数 + 添加投票用户
        const updatedElection = await Election.findOneAndUpdate(
            { election_name: electionSlug },
            {
                $push: { voters: username },
                $inc: { [`votes.${candidateIndex}`]: 1 }
            },
            { new: true }
        );

        res.json({ success: !!updatedElection });
    } catch (error) {
        console.error("Error in Vote:", error);
        res.status(500).json({ success: false, error: error.message });
    }
};

export default Vote;

内容的提问来源于stack exchange,提问作者Vraj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:58:28