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

Express+MongoDB项目必填字段为空仍创建文档问题求助

问题分析与解决方案

你遇到的问题根源有两个:

  1. Mongoose中数组类型的required: true仅验证字段存在,空数组[]会被视为合法值(因为它是一个存在的数组实例),无法阻止空数组的保存。
  2. 自定义的pre("save")钩子判断逻辑错误:空数组[]在JavaScript中是真值(Boolean([]) === true),所以!manga[field]的条件无法捕获空数组的情况。

方案1:使用Mongoose内置数组验证(推荐)

直接在Schema中为数组字段添加自定义验证器,确保数组非空且每个元素都是有效字符串,不需要额外的钩子:

import mongoose from "mongoose";

const mangaSchema = new mongoose.Schema(
  {
    name: {
      type: [String],
      required: true,
      validate: {
        validator: function(arr) {
          // 验证数组非空,且每个元素是 trimmed 后非空的字符串
          return arr.length > 0 && arr.every(str => typeof str === 'string' && str.trim().length > 0);
        },
        message: "name数组不能为空,且每个元素必须是非空字符串"
      }
    },
    artist: {
      type: [String],
      required: true,
      validate: {
        validator: function(arr) {
          return arr.length > 0 && arr.every(str => typeof str === 'string' && str.trim().length > 0);
        },
        message: "artist数组不能为空,且每个元素必须是非空字符串"
      }
    },
    // 其他字段保持不变
    summary: { type: String },
    chapters: { type: Number },
    comicStatus: { type: String },
    readingStatus: { type: String },
    rating: { type: Number },
    review: { type: String },
    tags: [String],
  },
  {
    timestamps: true,
  }
);

export default mongoose.model("Manga", mangaSchema);

方案2:修正pre("save")钩子逻辑

如果需要保留自定义钩子,修改判断条件为检查数组长度和元素有效性:

mangaSchema.pre("save", function (next) {
  const manga = this;
  const requiredFields = ["name", "artist"];
  const invalidFields = [];

  requiredFields.forEach((field) => {
    // 检查字段存在、数组非空、且每个元素trim后非空
    if (!manga[field] || manga[field].length === 0 || !manga[field].every(str => str.trim().length > 0)) {
      invalidFields.push(field);
    }
  });

  if (invalidFields.length > 0) {
    const error = new Error(
      `无效字段:${invalidFields.join(", ")} - 数组不能为空且元素必须是非空字符串`
    );
    error.name = "ValidationError";
    return next(error);
  }

  next();
});

补充说明

  • 内置验证的优势:不仅在save()时生效,若在更新操作(如findOneAndUpdate)中添加{ runValidators: true }选项,也会触发验证,覆盖更多场景。
  • 你的POST请求处理函数无需修改,已正确捕获ValidationError并返回400状态码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:05:00