最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do you iterate over Mongoose model properties within a middleware function? - Stack Overflow

programmeradmin4浏览0评论

I'm attempting to iterate over fields in a mongoose model within a middleware function. The current context this is the model object itself. So I have a function in which the context is a Javascript object like this:

{
  lastName: 'Wilkens',
  firstName: 'Elepart',
  name: 'Elepart Wilkens',
  username: 'eK',
  bio: '<script>alert(\'this is a hack!!\')',
  _id: 53b17dd0e8c5af50c1d73bc6,
  language: 'en',
  country: 'USA',
  online: true
}

I want to iterate over this object (which is represented in the current function with this). Every time I attempt to iterate with loops, it prints out values that look like internal Javascript metadata. Is it possible to iterate over this within a function if this represents an object?

Here's the actual middleware function:

userSchema.pre('save', function (next) {
    console.log(this); // This prints precisely the same object I have copied above

    var fields = Object.keys(this);

    for(var i = 0; i < fields.length; i++) {
        console.log(this[fields[i]]);
    }

    for(var key in this) {
      if(this.hasOwnProperty(key)) {
        console.log(this[key]);
      }
    }
});

And the output is:

{ 
 strictMode: true,
 selected: undefined,
 shardval: undefined,
 saveError: undefined,
 validationError: undefined,
 adhocPaths: undefined,
 removing: undefined,
 inserting: undefined,
 version: undefined,
 getters: {},
 _id: undefined,
 populate: undefined,
 populated: undefined,
 wasPopulated: false,
 scope: undefined,
 activePaths: 
   { paths: 
      { username: 'modify',
        firstName: 'modify',
        name: 'modify',
        online: 'default',
        country: 'default',
        language: 'default',
        _id: 'default',
        bio: 'modify',
        lastName: 'modify' },
     states: { default: [Object], init: {}, modify: [Object], require: {} },
     stateNames: [ 'require', 'modify', 'init', 'default' ],
     map: [Function] },
  ownerDocument: undefined,
  fullPath: undefined }
true
undefined
0
{ online: true,
  country: 'USA',
  language: 'en',
  _id: 53b1825a00ed9af7c12eedf9,
  bio: '<script>alert(\'this is a hack!!\')',
  username: 'yK',
  name: 'Yershay Wilkens',
  firstName: 'Yershay',
  lastName: 'Wilkens' }
{ save: 
   [ { [Function] isAsync: false },
     { [Function: checkForExistingErrors] isAsync: false },
     { [Function: validation] isAsync: false },
     { [Function] isAsync: false },
     { [Function] isAsync: false } ],
  validate: [ { [Function] isAsync: false } ] }
{ save: [], validate: [] }
{ [Function] numAsyncPres: 0 }
{ [Function] numAsyncPres: 0 }
{}

I'm attempting to iterate over fields in a mongoose model within a middleware function. The current context this is the model object itself. So I have a function in which the context is a Javascript object like this:

{
  lastName: 'Wilkens',
  firstName: 'Elepart',
  name: 'Elepart Wilkens',
  username: 'eK',
  bio: '<script>alert(\'this is a hack!!\')',
  _id: 53b17dd0e8c5af50c1d73bc6,
  language: 'en',
  country: 'USA',
  online: true
}

I want to iterate over this object (which is represented in the current function with this). Every time I attempt to iterate with loops, it prints out values that look like internal Javascript metadata. Is it possible to iterate over this within a function if this represents an object?

Here's the actual middleware function:

userSchema.pre('save', function (next) {
    console.log(this); // This prints precisely the same object I have copied above

    var fields = Object.keys(this);

    for(var i = 0; i < fields.length; i++) {
        console.log(this[fields[i]]);
    }

    for(var key in this) {
      if(this.hasOwnProperty(key)) {
        console.log(this[key]);
      }
    }
});

And the output is:

{ 
 strictMode: true,
 selected: undefined,
 shardval: undefined,
 saveError: undefined,
 validationError: undefined,
 adhocPaths: undefined,
 removing: undefined,
 inserting: undefined,
 version: undefined,
 getters: {},
 _id: undefined,
 populate: undefined,
 populated: undefined,
 wasPopulated: false,
 scope: undefined,
 activePaths: 
   { paths: 
      { username: 'modify',
        firstName: 'modify',
        name: 'modify',
        online: 'default',
        country: 'default',
        language: 'default',
        _id: 'default',
        bio: 'modify',
        lastName: 'modify' },
     states: { default: [Object], init: {}, modify: [Object], require: {} },
     stateNames: [ 'require', 'modify', 'init', 'default' ],
     map: [Function] },
  ownerDocument: undefined,
  fullPath: undefined }
true
undefined
0
{ online: true,
  country: 'USA',
  language: 'en',
  _id: 53b1825a00ed9af7c12eedf9,
  bio: '<script>alert(\'this is a hack!!\')',
  username: 'yK',
  name: 'Yershay Wilkens',
  firstName: 'Yershay',
  lastName: 'Wilkens' }
{ save: 
   [ { [Function] isAsync: false },
     { [Function: checkForExistingErrors] isAsync: false },
     { [Function: validation] isAsync: false },
     { [Function] isAsync: false },
     { [Function] isAsync: false } ],
  validate: [ { [Function] isAsync: false } ] }
{ save: [], validate: [] }
{ [Function] numAsyncPres: 0 }
{ [Function] numAsyncPres: 0 }
{}
Share Improve this question edited Jul 3, 2014 at 15:03 Glen Selle asked Jun 30, 2014 at 15:16 Glen SelleGlen Selle 3,9564 gold badges38 silver badges59 bronze badges 6
  • 1 Can you post the loop you are currently using? – Duane Commented Jun 30, 2014 at 15:18
  • 1 or could you set up a fiddle ? i think it is possible – john Smith Commented Jun 30, 2014 at 15:18
  • 1 Without more code we can't help you. Though here is an example of how it could work: jsbin./gomisuyu/1 – Yoshi Commented Jun 30, 2014 at 15:23
  • I've added more code. A JSfiddle wouldn't be as helpful since this is all with Mongoose, so it be a bit hard to replicate in the browser. – Glen Selle Commented Jun 30, 2014 at 15:25
  • When iterating over an object (not an array) try using "for in" for ( key in object ) as well as hasOwnProperty as answered here stackoverflow./questions/684672/… – tastybytes Commented Jun 30, 2014 at 15:27
 |  Show 1 more ment

3 Answers 3

Reset to default 6

You're using integer indexes instead of the string references from the fields array. It should be:

var fields = Object.keys(this);

for(var i = 0; i < fields.length; i++) {
    console.log(this[fields[i]]);
}

(e.g., you were doing this[1], this[2], instead of this[fields[1]])

@JohnnyHK's ment worked for me:

const user = new User();
const schemaKeys = Object.keys(user.toObject());

I found a slightly different way to acplish what I wanted which was to iterate over the model properties of a Mongoose model within a middleware function. This uses async.js, but you could refactor it to use a generic JS loop or any other control flow library. The key is to get an array of the document's fields, then you can iterate over those and get/set the values using the current context with this. As far as I know, this will not coerce non-string values into strings. I've tested it with strings, numbers, booleans and objectIds and they are successfully saved as their original data types.

yourSchema.pre('save', function (next) {
  var self = this;

  // Get the document's fields
  var fields = Object.keys(this._doc);

  // Do whatever you want for each field
  async.each(fields, function(field, cb) {
    self[field] = validator.escape(self[field]);
    cb();
  }, function(err){
    next();
  });
});
发布评论

评论列表(0)

  1. 暂无评论