Заполните массив ObjectId в ответ, используя узел js - PullRequest
0 голосов
/ 04 сентября 2018

Я новичок в программировании на NodeJS и искал решения о том, как заполнить атрибуты ответа в объекте json типа Object Array.

Ниже приведен пример ответа от моего сервиса -

{
        "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
    }

Я хотел бы заполнить ObjectId в атрибуте массива Roles реальным именем вместо идентификаторов.

Как мне это сделать.

Ниже описан способ определения схемы пользователя и ролей

.

Модель пользователя

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);
    });
});

Исключение -

<code><!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)

Ответы [ 3 ]

0 голосов
/ 04 сентября 2018

Вы можете использовать заполнить от Mongoose, чтобы заполнить RoleName вместо ObjectId refs

Mongoose имеет более мощную альтернативу под названием 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`
  }
}
0 голосов
/ 04 сентября 2018

Понял проблему.

В определении пользовательской схемы мне также пришлось определить схему ролей.

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
    }
0 голосов
/ 04 сентября 2018

Простое использование функции мангуста populate()

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

Приветствия

...