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

MongoDB重复键错误解决方案:Pinterest克隆传帖遇E11000问题

同一账号上传第二篇帖子触发MongoDB重复键错误的解决方案

问题描述

开发Pinterest克隆项目时,同一账号上传第二篇及后续帖子时触发MongoDB E11000重复键错误,错误提示posts集合的username_1索引存在重复的null键值。

相关代码

User Schema

const mongoose = require('mongoose');
const plm = require('passport-local-mongoose');

mongoose.connect('mongodb://127.0.0.1:27017/DataVault');

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    unique: true
  },
  email: {
    type: String,
  },
  password: String,

  post: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: "Post",
    }
  ],
  ProfileImage: String,
});

userSchema.plugin(plm);

module.exports = mongoose.model('User', userSchema);

Post Schema

const mongoose = require('mongoose');
const plm = require('passport-local-mongoose');

mongoose.connect('mongodb://127.0.0.1:27017/DataVault');

const postSchema = new mongoose.Schema({
  PostText: {
    type: String,
  },
  image: {
    type: String
  },
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User",
  }
});

postSchema.plugin(plm);

module.exports = mongoose.model('Post', postSchema);

帖子创建路由

// post creaetion and uploading
router.post("/postUpload", isLoggedIn, uploads.single("postImage"), async function (req, res, next) {
  if (!req.file) {
    return res.status(404).send("Something Went Wrong!!!😡");
  }

  const user = await userModel.findOne({ username: req.session.passport.user });
  const post = await postModel.create({
    PostText: req.body.fileCaption,
    image: req.file.filename,
    user: user._id
  });

  user.post.push(post._id);
  await user.save();

  console.log("Post Successfully Saved ✌");
  res.redirect("/profile");
});

报错信息

throw new error_1.MongoServerError(res.writeErrors[0]);

^

MongoServerError: E11000 duplicate key error collection: DataVault.posts index: username_1 dup key: { username: null }

at InsertOneOperation.execute (D:\backend\Codes\pinterest\node_modules\mongodb\lib\operations\insert.js:48:19)

at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

at async executeOperationAsync (D:\backend\Codes\pinterest\node_modules\mongodb\lib\operations\execute_operation.js:106:16) {

index: 0,

code: 11000,

keyPattern: { username: 1 },

keyValue: { username: null },

[Symbol(errorLabels)]: Set(0) {}

}

解决方案

核心问题

Post Schema错误地使用了passport-local-mongoose插件,该插件会自动为Schema添加username字段并创建唯一索引。但帖子模型不需要这个字段,导致每次创建帖子时username字段为null,而MongoDB中唯一索引不允许多个文档的字段值为null,因此第二次上传时触发重复键错误。

修复步骤

  1. 移除Post Schema中的passport-local-mongoose插件
    编辑Post Schema文件,删除不必要的插件引入和调用,修改后的代码如下:

    const mongoose = require('mongoose');
    
    // 移除不必要的plm引入
    // const plm = require('passport-local-mongoose');
    
    // 建议统一在项目入口文件中连接数据库,此处可移除
    // mongoose.connect('mongodb://127.0.0.1:27017/DataVault');
    
    const postSchema = new mongoose.Schema({
      PostText: {
        type: String,
      },
      image: {
        type: String
      },
      user: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "User",
      }
    });
    
    // 移除插件调用
    // postSchema.plugin(plm);
    
    module.exports = mongoose.model('Post', postSchema);
    
  2. 清理MongoDB中的重复索引
    进入MongoDB Shell执行以下命令:

    # 进入MongoDB Shell(根据版本使用mongosh或mongo)
    mongosh
    # 切换到目标数据库
    use DataVault
    # 删除posts集合的username_1索引
    db.posts.dropIndex("username_1")
    
  3. 优化数据库连接
    不要在每个Schema文件中重复调用mongoose.connect,建议在项目入口文件(如app.js或server.js)中统一配置数据库连接,避免重复连接造成资源浪费。

  4. 优化User Schema(可选)
    User Schema中手动定义的password字段可以移除,因为passport-local-mongoose会自动创建hash和salt字段来存储加密后的密码,手动定义可能导致冲突。

验证修复

重启后端服务,使用同一账号多次上传帖子,确认不再触发重复键错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:05:37