使用节点js

时间:2018-09-04 11:52:08

标签: node.js mongoose objectid

我是NodeJS编程的新手,正在寻找有关如何在JSON Object中填充对象数组类型的响应属性的解决方案。

以下是我的服务的示例响应-

{
        "Roles": [
            "5b7fd72537651320a03494f8",
            "5b7fdc06e3fcb037d016e26a"
        ],
        "_id": "5b8e530be2d4630fd4f4b34a",
        "Username": "ctucker",
        "FirstName": "Chris",
        "LastName": "Tucker",
        "Email": "ctucker@innovate.com",
        "createdAt": "2018-09-04T09:40:27.091Z",
        "updatedAt": "2018-09-04T09:40:27.091Z",
        "__v": 0
    }

我想用实际名称而不是ID填充Roles数组属性中的ObjectId。

我应该怎么做。

以下是方法,我已经定义了用户和角色架构

用户模型

const userSchema = new mongoose.Schema({

    Username: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 255,
        unique: true
    },
    FirstName: {
        type: String
    },
    LastName: {
        type: String
    },
    Email: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 255
    },
    Password: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 1024
    },
    Roles: [{type: mongoose.Schema.Types.ObjectId, ref: Roles}],
    Active: {type: Boolean, default: true},
    SuperUser: {type: Boolean, default: false}
},{
    timestamps: true
});

角色模型

const rolesSchema = new mongoose.Schema({
    RoleName: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 255,
        unique: true
    },
    Description: {
        type: String
    },
    Active: {type: Boolean, default: true}
}, {
    timestamps: true
});

创建用户

router.post('/', [auth, admin], async (req, res) => {

  const { error } = validate(req.body); 
  if (error) return res.status(400).send(error.details[0].message);

  let user = await User.findOne({ Username: req.body.Username });
  if (user) return res.status(400).send('User with username: ', req.body.Username, 'already exists. Please try with any other username');

  let roleInput = [];

  if(req.body.Roles !== null) {
    req.body.Roles.forEach( async (element) => {
      objectId = mongoose.Types.ObjectId(element);
      roleInput.push(objectId);
    });
  }

  console.log('Role info ', roleInput);

  user = new User(_.pick(req.body, ['Username', 'FirstName', 'LastName' ,'Email', 'Password', 'Active','SuperUser']));

  console.log('User Input => ', user);

  const salt = await bcrypt.genSalt(10);
  user.Password = await bcrypt.hash(user.Password, salt);

  roleInput.forEach( async (objectId) => {
    user.Roles.push(objectId);
  });  

  console.log('User Input after role addition => ', user);

  await user.save();

  const token = user.generateAuthToken();
  res.header('x-auth-token', token).send(_.pick(user, ['_id', 'FirstName', 'LastName' ,'Email', 'Roles']));

});

我想获得RoleName而不是ObjectId作为响应。 在这方面的任何帮助将不胜感激。

忘记提及我已经尝试使用populate方法,但是看到以下异常。

我如何使用填充方法-

router.get('/', auth, (req, res, next) => {
  var request_params = url.parse(req.url,true).query;
  var searchQuery = (request_params.mode === 'active') ? {'Active': true} : {};
  User.find(searchQuery)
    .populate('Roles')
    .select(['-Password', '-Active', '-SuperUser'])
    .then((users) => {
        res.send(users);
    }, (error) => {
      next(error);
    });
});

例外-

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <link rel="stylesheet" href="/stylesheets/style.css">
    </head>
    <body>
        <h1>Schema hasn't been registered for model &quot;[object Object]&quot;.
Use mongoose.model(name, schema)</h1>
        <h2></h2>
        <pre>MissingSchemaError: Schema hasn't been registered for model &quot;[object Object]&quot;.
Use mongoose.model(name, schema)
    at new MissingSchemaError (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\error\missingSchema.js:20:11)
    at NativeConnection.Connection.model (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\connection.js:791:11)
    at getModelsMapForPopulate (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\model.js:4016:20)
    at populate (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\model.js:3505:21)
    at _populate (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\model.js:3475:5)
    at utils.promiseOrCallback.cb (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\model.js:3448:5)
    at Object.promiseOrCallback (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\utils.js:232:14)
    at Function.Model.populate (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\model.js:3447:16)
    at cb (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\lib\query.js:1678:17)
    at result (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\utils.js:414:17)
    at executeCallback (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\utils.js:406:9)
    at handleCallback (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\utils.js:128:55)
    at cursor.close (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\operations\cursor_ops.js:211:62)
    at handleCallback (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\utils.js:128:55)
    at completeClose (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\cursor.js:887:14)
    at Cursor.close (C:\Vijay-Docs\Personal\vuejs-ws\AgileCenter\agilecenterservices\node_modules\mongoose\node_modules\mongodb\lib\cursor.js:906:10)</pre>
    </body>
</html>

3 个答案:

答案 0 :(得分:0)

使用猫鼬populate()函数简单

const user = await User.findOne().populate('Roles');
// output => user.Roles // will be array of mongo documents

欢呼

答案 1 :(得分:0)

您可以使用猫鼬的populate来填充RoleName而不是ObjectId裁判

  

猫鼬有一个更强大的替代方法,称为 populate(),它使您可以引用其他集合中的文档。

'use strict';

let user = await User.findOne({
  Username: req.body.Username
}).populate('Roles');

if (user && user.Roles.length > 0) {
  for (let role of user.Roles) {
    console.log(role.RoleName);// logs `RoleName`
  }
}

答案 2 :(得分:0)

理解了这个问题。

在用户架构定义中,我还必须定义角色架构。

const rolesSchema = new mongoose.Schema({
    RoleName: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 255,
        unique: true
    },
    Description: {
        type: String
    },
    Active: {type: Boolean, default: true}
}, {
    timestamps: true
});

const Roles = mongoose.model('Roles', rolesSchema);

const userSchema = new mongoose.Schema({

    Username: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 255,
        unique: true
    },
    FirstName: {
        type: String
    },
    LastName: {
        type: String
    },
    Email: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 255
    },
    Password: {
        type: String,
        required: true,
        minlength: 5,
        maxlength: 1024
    },
    Roles: [{type: mongoose.Schema.Types.ObjectId, ref: 'Roles'}],
    Active: {type: Boolean, default: true},
    SuperUser: {type: Boolean, default: false}
},{
    timestamps: true
});

在用户架构中添加角色架构定义后,邮递员的响应确实会填充RoleName作为响应。

{
        "Roles": [
            {
                "RoleName": "AC-User"
            },
            {
                "RoleName": "AC-PMLead"
            }
        ],
        "_id": "5b8e48e2f3372a098c6e5346",
        "Username": "mcmillan",
        "FirstName": "McMillan",
        "LastName": "McMillan",
        "Email": "mcmillan@innovate.com",
        "createdAt": "2018-09-04T08:57:07.029Z",
        "updatedAt": "2018-09-04T08:57:07.029Z",
        "__v": 0
    }