简体   繁体   中英

Node.Js Express and Mongoose Response Model Modify

I'm quite new to Node.js development. Also callbacks still quite bedazzle me although I have some experience with async functions.

I'm using mongoose's .find() function to search in a Users collection in the DB. The problem is I also want to display these users but I wouldn't want to display all the properties availible in the Database.

...
function(req,res){
    User.find(function(err,users){
        res.json(users);
    }) 
}
...

This is how I'm currently getting all my users in the DB, but this also return passwords and other sensitive information. I would like to know the most effiecient way to "convert" this data into the same object without some properties or with altered properties like adding a "fullName" comprised of firstName + lastName;

So when returning all the users I would like to have something like

...
function(req,res){
    User.find(function(err,users){
        res.json(users.convertToOtherModel());
    }) 
}
...

Not sure the "convertToOtherModel" function can be placed somewhere so that it works on users... but any idea on how to do this would help!

You can do something like this to return only some of the properties:

function filterUser(user) {
  let { property1, property2 } = user;
  return { property1, property2 };
}
res.json( users.map(filterUser) );

Or a more portable way using lodash:

res.json( users.map(user => _.pick(user, ['prop1', 'prop2']));

See: https://lodash.com/docs/4.17.4#pick

To use the lodash version you first need to add:

const _ = require('lodash');

to your code, and run this in your project's directory:

npm install lodash --save
personSchema
    .virtual('fullName')
    .get(function () {
        return this.name.first + ' ' + this.name.last;
    })
    .set(function (v) {
        this.name.first = v.substr(0, v.indexOf(' '));
        this.name.last = v.substr(v.indexOf(' ') + 1);
    })
  1. For something like FullName you can create virtual schemas.

    Link here: http://mongoosejs.com/docs/guide.html

  2. You will have to choose what columns you want to output, i am not sure if you can specifically blacklist a column(All columns minus password column)

Instead of making query to return all fields you can pass second argument to find() and specify which fields you want or don't want to return

User.find({}, {password: 0}, function(error, users) {
  console.log(users)
})

You can also use aggregation framework and create new field by concating values of different fields

User.aggregate([
    {$project: {
        username: '$username',
        fullName: {$concat: ['$firstName', ' ', '$lastName']}
    }}
    ], function(error, users) {
        console.log(users)
    })

Override toJSON method of your User schema.

UserSchema.methods.toJSON = function () {
  var user = this;
  // Modify your document object here
  return { fullName: user.firstName + " " + user.lastName }
  // Pick other fields too if you want
  // _.pick(user, ["otherField"]);
};

Then send them like so -

User.find(function(err,users){
  res.json(users);
}) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM