如何在中间件函数中迭代Mongoose模型属性?

Gle*_*lle 4 javascript loops mongoose

我试图在中间件函数中迭代mongoose模型中的字段.当前上下文this是模型对象本身.所以我有一个函数,其中上下文是这样的Javascript对象:

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

我想迭代这个对象(在当前函数中表示this).每次我尝试使用循环进行迭代时,它都会打印出看起来像内部Javascript元数据的值.this如果this代表一个对象,是否可以在函数内迭代?

这是实际的中间件功能:

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]);
      }
    }
});
Run Code Online (Sandbox Code Playgroud)

输出是:

{ 
 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 }
{}
Run Code Online (Sandbox Code Playgroud)

小智 6

您正在使用整数索引而不是fields数组中的字符串引用.它应该是:

var fields = Object.keys(this);

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

(例如,你在做this[1],this[2]而不是this[fields[1]])

  • @Glen尝试将第一行更改为:`var fields = Object.keys(this.toObject());` (3认同)

Ste*_*ush 6

@JohnnyHK 的评论对我有用:

const user = new User();
const schemaKeys = Object.keys(user.toObject());
Run Code Online (Sandbox Code Playgroud)


Gle*_*lle 4

我发现了一种稍微不同的方法来完成我想要的任务,即在中间件函数中迭代 Mongoose 模型的模型属性。它使用async.js,但您可以重构它以使用通用 JS 循环或任何其他控制流库。关键是获取文档字段的数组,然后您可以迭代这些字段并使用当前上下文获取/设置值this。据我所知,这不会将字符串值强制转换为字符串。我已经用字符串、数字、布尔值和 objectId 对其进行了测试,它们已成功保存为其原始数据类型。

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();
  });
});
Run Code Online (Sandbox Code Playgroud)