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

我使用 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 模型中的验证。


潇潇雨雨
浏览 95回答 2
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);  }});

holdtom

您可以使用 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();
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript