为了账号安全,请及时绑定邮箱和手机立即绑定

MongooseJS - 插入子文档而不验证文档

MongooseJS - 插入子文档而不验证文档

潇潇雨雨 2023-09-07 16:07:12
我使用 Mongoose 和 Javascript (NodeJS) 来读取/写入 MongoDB。我有一个文档(父文档),其中有一堆子文档(子文档)。我的文档和子文档都在其模型中定义了验证(required: true以及验证用户是否将文本放入字段的函数)。当尝试将新的子文档推送到数据库时,Mongoose 拒绝我的推送,因为文档验证失败。这让我很困惑,因为我并没有尝试使用子文档创建新文档,我只是尝试将新的子文档推送到现有文档中。这是我的(示例)猫鼬模型:const mongoose = require('mongoose');const requiredStringValidator = [  (val) => {    const testVal = val.trim();    return testVal.length > 0;  },  // Custom error text  'Please supply a value for {PATH}',];const childrenSchema = new mongoose.Schema({  childId: {    type: mongoose.Schema.Types.ObjectId,  },  firstName: {    type: String,    required: true,    validate: requiredStringValidator,  },  lastName: {    type: String,    required: true,    validate: requiredStringValidator,  },  birthday: {    type: Date,    required: true,  },});const parentSchema = new mongoose.Schema(  {    parentId: {      type: mongoose.Schema.Types.ObjectId,    },    firstName: {      type: String,      required: true,      validate: requiredStringValidator,    },    lastName: {      type: String,      required: true,      validate: requiredStringValidator,    },    children: [childrenSchema],  },  { collection: 'parentsjustdontunderstand' },);我可以通过以下 MongoDB 命令成功地将新的子子文档推送到父文档中:db.parentsjustdontunderstand.update({    firstName: 'Willard'}, {    $push: {        children: {    "firstName": "Will",    "lastName": "Smith",    "birthday": "9/25/1968"        }    }});但是,当我按照 Mongoose 文档添加子文档到数组并尝试通过 Mongoose 添加它时,它失败了。出于测试目的,我使用 Postman 并对端点执行 PUT 请求。以下是req.body:{    "firstName": "Will",    "lastName": "Smith",    "birthday": "9/25/1968"}我的代码是:const { Parent } = require('parentsModel');const parent = new Parent();parent.children.push(req.body);parent.save();我得到的回报是:ValidationError: Parent validation failed: firstName: Path `firstName` is required...`它列出了父文档的所有验证要求。我可以为我做错的事情提供一些帮助。作为记录,我在 Stackoverflow 上查看了这个答案:Push items into mongo array via mongoose,但我看到的大多数示例都没有显示或讨论其 Mongoose 模型中的验证。
查看完整描述

2 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞


这是不正确的:


const child = {

  children: {

      "firstName": "Will",

      "lastName": "Smith",

      "birthday": "9/25/1968"

  }

}

这是正确的:


const child = {

    "firstName": "Will",

    "lastName": "Smith",

    "birthday": "9/25/1968"

}

该记录被插入数据库并保存,但由于我将其作为 PUT 请求启动,因此在使用HTTP 200 OK. 下面是整个解决方案的正确代码,但是请记住,该res.status代码仅在这种情况下才是必需的,因为我是通过 PUT 请求来模仿代码的。


猫鼬型号:


const mongoose = require('mongoose');


const requiredStringValidator = [

  (val) => {

    const testVal = val.trim();

    return testVal.length > 0;

  },

  // Custom error text

  'Please supply a value for {PATH}',

];

const childrenSchema = new mongoose.Schema({

  childId: {

    type: mongoose.Schema.Types.ObjectId,

  },

  firstName: {

    type: String,

    required: true,

    validate: requiredStringValidator,

  },

  lastName: {

    type: String,

    required: true,

    validate: requiredStringValidator,

  },

  birthday: {

    type: Date,

    required: true,

  },

});

const parentSchema = new mongoose.Schema(

  {

    parentId: {

      type: mongoose.Schema.Types.ObjectId,

    },

    firstName: {

      type: String,

      required: true,

      validate: requiredStringValidator,

    },

    lastName: {

      type: String,

      required: true,

      validate: requiredStringValidator,

    },

    children: [childrenSchema],

  },

  { collection: 'parentsjustdontunderstand' },

);

const mongooseModels = {

  Parent: mongoose.model('Parent', parentSchema),

  Children: mongoose.model('Children', childrenSchema),

};

module.exports = mongooseModels;

以下是req.body:


{

    "firstName": "Will",

    "lastName": "Smith",

    "birthday": "9/25/1968"

}

代码是:


const { Parent } = require('parentsModel');

const parent = await Parent.findOne({firstName: 'Willard'});

parent.children.push(req.body);

parent.save((err, doc) => {

  if (err) {

    res.status(500).json({

      message: 'Error finding active projects',

      error: err,

    });

  } else {

    res.status(200).json(doc);

  }

});


查看完整回答
反对 回复 2023-09-07
?
holdtom

TA贡献1805条经验 获得超10个赞

您可以使用 mongo 查询将子级推送到父级,因为在 中update,第一个对象是查找推送的文档。


语法如下:update({query},{update},{options})。因此,您正在寻找包含firstName: 'Willard'子项的文档并将其添加到其中。


这里一切正常,所有字段都存在,父级存在于集合中,所以没有问题。


但使用

const parent = new Parent();

parent.children.push(req.body);

parent.save();

您的父对象是空的(除非构造函数填充所有字段,但我认为这不是一个好主意)。


如果你尝试这样做:


var parent = await model.findOne({firstName: 'Willard'})

parent.children.push(req.body);

parent.save();

然后应该可以工作。


在本例中,对象parent是从集合中检索的,因此它包含所有必需的字段。


我将进行编辑以更好地解释为什么这两个查询不相同。


基本上,您尝试保存的子对象的结构不同db.collection.update。请注意,您创建的要插入到集合中的对象child只有一个名为 的属性children。它不具有必要的属性,例如firstName...


我将使用纯 JS 来查看console.log()输出是什么并查看差异。


你的 mongo 查询推送一个像这样的对象(翻译成 js 语言):


var array = []

array.push(

    children = {

        "firstName": "Will",

        "lastName": "Smith",

        "birthday": "9/25/1968"

    }

)


console.log(array)


但您正在以这种方式创建对象:


const child = {

  children: {

      "firstName": "Will",

      "lastName": "Smith",

      "birthday": "9/25/1968"

  }

}


console.log(child)


现在你看出区别了吗?一个对象是子对象本身,另一个对象具有属性children 和必要的字段。


那么让我们将这两段代码组合起来:


const child = {

  children: {

      "firstName": "Will",

      "lastName": "Smith",

      "birthday": "9/25/1968"

  }

}


const children = {

        "firstName": "Will",

        "lastName": "Smith",

        "birthday": "9/25/1968"

    }


var array = [child,children]

console.log(array)


因此,对于您的代码,如果您使用:


parent.children.push(child.children);

parent.save();

应该有效。children但是,最好的方法不是在里面创建对象const child


尝试使用:


const child = {

  "firstName": "Will",

  "lastName": "Smith",

  "birthday": "9/25/1968"

}

parent.children.push(child);

parent.save();


查看完整回答
反对 回复 2023-09-07
  • 2 回答
  • 0 关注
  • 67 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信