NodeJS & Mongoose:将元素添加到现有的空数组

NodeJS & Mongoose: Add element to existing empty array

我正在构建一个 NodeJS 应用程序,用于根据 MSQL 数据库中的数据创建报告。所有与应用程序相关的数据都使用 Mongoose 存储在 MongoDB 中。我的猫鼬模型包含一个空数组,然后由用户通过 Rest-API 填充该数组。 向数组添加新元素时出现错误。我已经用 model.array.push(object); model.save()findByIdAndUpdate(...) 试过了。找到我的代码,包括以下两种不同的尝试:

猫鼬模式

var sqlSchema = mongoose.Schema({ // Schema to store information about SQL-procedures
    'name': String,
    'inputs': [
        {
            'name': String,
            'type': String,
            'value': String,
            'adjustable': Boolean
        }
    ]
});

休息 API

我的应用程序通过 POST:

接受 'inputs' 数组的新元素
var mongoose = require('mongoose'),
    SqlProcedure = mongoose.model('SqlProcedure');

// ...

router.post('/sql/:id/inputs', function(req, res) {
    SqlProcedure.findById(req.params.id, function(err, sql) {
        if(err) {
            res.send(msg.error('error retrieving sql-procedure', err));
        } else {
            if(sql.inputs.length > 0) {     // catch empty array
                for(var key in sql.inputs) {
                    if(sql.inputs[key].name == req.body.name) {
                        return res.send(msg.error('input already in inputs', err));
                    }
                }
            }

            var data = req.body;

            var input = {
                name: data.name,
                type: data.type,
                value: data.value,
                adjustable: data.adjustable
            };

            // attempt one or two
        }
    });
});

尝试一:

            sql.inputs.push(input); // EXCEPTION 1

            sql.save(function(err) {
                // fancy errorhandling
                return res.send(msg.ok(sql));
            });

尝试二:

            SqlProcedure.findByIdAndUpdate(req.params.id,
                {$push: {inputs: input}}, // EXCEPTION 2
                {safe: true, upsert: true},
                function(err, sql) {
                    // fancy errorhandling
                    res.send(msg.ok('input added to sql-procedure' + req.params.id));
                }
            );

例外情况

尝试一:

throw new CastError('string', value, this.path);
  ^
Error
    at MongooseError.CastError (\node_modules\mongoose\lib\error\cast.js:18:16)
    at SchemaString.cast (\node_modules\mongoose\lib\schema\string.js:434:9)
    at Array.MongooseArray.mixin._cast (\node_modules\mongoose\lib\types\array.js:124:32)
    at Array.MongooseArray.mixin._mapCast (\node_modules\mongoose\lib\types\array.js:295:17)
    at Object.map (native)
    at Array.MongooseArray.mixin.push (\node_modules\mongoose\lib\types\array.js:308:25)
    at Query.<anonymous> (\app\api\sql_procedure.js:69:28)
    at \node_modules\mongoose\node_modules\kareem\index.js:177:19
    at \node_modules\mongoose\node_modules\kareem\index.js:109:16
    at doNTCallback0 (node.js:417:9)
    at process._tickCallback (node.js:346:13)

尝试二:

"stack": "Error
at MongooseError.CastError (\node_modules\mongoose\lib\error\cast.js:18:16)
at SchemaArray.cast (\node_modules\mongoose\lib\schema\array.js:156:15)
at SchemaArray.cast (\node_modules\mongoose\lib\schema\array.js:167:17)
at Query._castUpdateVal (\node_modules\mongoose\lib\query.js:2384:22)
at Query._walkUpdatePath (\node_modules\mongoose\lib\query.js:2298:27)
at Query._castUpdate (\node_modules\mongoose\lib\query.js:2227:23)
at castDoc (\node_modules\mongoose\lib\query.js:2430:18)
at Query._findAndModify (\node_modules\mongoose\lib\query.js:1752:17)
at Query._findOneAndUpdate (\node_modules\mongoose\lib\query.js:1620:8)
at \ITZReport\node_modules\mongoose\node_modules\kareem\index.js:156:8
at \node_modules\mongoose\node_modules\kareem\index.js:18:7
at doNTCallback0 (node.js:417:9)\n    at process._tickCallback (node.js:346:13)",
    "message": "Cast to undefined failed for value \"[object Object]\" at path \"inputs\"",
    "name": "CastError",
    "value": [
        {
            "adjustable": "true",
            "value": "Harry Potter",
            "type": "String",
            "name": "salesman"
        }
    ],
    "path": "inputs"

待插入数据

{ name: 'salesman',
  type: 'String',
  value: 'Harry Potter',
  adjustable: 'true' }

我是 NodeJS 和 mongoose 的新手,我花了很多时间尝试自己解决这个问题。如果有人能帮助我,那就太好了!

提前致谢, dj2bee

更新

我想我应该阐明用户与REST交互的过程-API:

  1. 用户通过传递值创建了一条新记录 name。此时 name 已设置,inputs 数组 是空的。
  2. 下一步,用户将新记录添加到 inputs-一一排列。 name 保持原样且仅 新 inputs 被添加到数组中。
  3. 用户应该能够编辑或删除条目 inputs-数组。

adjustable 的数据类型更改为 String 没有做任何更改。我还尝试了对属性进行硬编码,而不是通过 HTTP-POST 传递它们 - 仍然是相同的异常。

您应该将要插入的数据设置为

{ name: 'salesman', 
  inputs: [{name: 'salesman',
  type: 'String',
  value: 'Harry Potter',
  adjustable: true}]}

即true 没有引号和输入作为数组

否则在架构中将可调整为字符串并在模型定义中将输入作为数组移除

var sqlSchema = mongoose.Schema({ // Schema to store information about SQL-procedures

            'name': String,
            'type': String,
            'value': String,
            'adjustable': String
        });

经过几个小时的网络搜索并测试了我代码中最奇怪的东西后,我找到了解决方案: 您不能在 mongoose-schema 中命名字段 'type'。 就是这样。

正确的代码如下所示:

猫鼬模式

var sqlSchema = mongoose.Schema({
    'name': String,
    'inputs': {
        'name': String,
        'datatype': String, // you can't name this field 'type'
        'value': String,
        'adjustable': Boolean
    }
});

休息 API

router.post('/sql/:id/inputs', function(req, res) {
    SqlProcedure.findById(req.params.id, function(err, sql) {
        if(err) {
            res.send(msg.error('error retrieving sql-procedure', err));
        } else {
            if(!sql) {
                return res.send(msg.error('no sql-procedure found with id '
                    + req.params.id, null));
            }
            // check for duplicates

            var data = req.body;

            var input = {
                'name': data.name,
                'datatype': data.type,
                'value': data.value,
                'adjustable': data.adjustable
            };

            SqlProcedure.findByIdAndUpdate(req.params.id,
                {$push: {inputs: input}},
                {safe: true, upsert: true},
                function(err, sql) {
                    // fancy error handling
                }
            );
        }
    });
});