dynamic定义mongoose模型方法

我是在一个function的情况下,能够根据不同的情况进行search。

它返回相同的数据集,它只是search不同的字段:userId或tagId。 因此,在我的代码中,我有这样的东西:

var findByMethod; if (searchBy === 'userId') { findByMethod = UserArticleModel.findByUser; } else { findByMethod = UserArticleModel.findByTag; } findByMethod(idToSearch, function (err, articles) {…}); 

findByUserfindByTagfindByTag中定义的静态方法

UserArticleModel.js

 var mongoose = require('mongoose'); var userArticleSchema = new mongoose.Schema({ … } }); userArticleSchema.statics.findByUser = function (userId, callback) { this.find({userId: userId}, function () {…}); }; userArticleSchema.statics.findByTag = function (tagId, callback) {…}; module.exports = mongoose.model('UserArticle', userArticleSchema); 

回到我的控制器中,当我这样做的时候:

 UserArticleModel.findByTag(idToSearch, function (err, articles) {…}); 

一切都很好,事情正确。 但是,当我dynamic调用通过我的variables的方法:

 findByMethod(idToSearch, function (err, articles) {…}); 

由于节点返回错误,所以出错了:

 DOMAINE ERROR CAUGHT: TypeError: Object #<Object> has no method 'find' 

我怀疑this不是被绑定到正确的范围,但我不明白为什么findByMethod === UserArticleModel.findByUser // true

我认为你正在使这个更需要参与。 虽然这是一个容易陷入“太字面”遵循logging的API示例,并基本思考“这是我需要如何硬编码,因为文档说这就是你怎么做”

JavaScript对象就是“对象”,因此仅仅分配“已命名”的静态方法实际上只是对象属性,这只是将已定义的“对象”中定义的“模式path”“循环”并设置你想要的“findByFieldName”方法的属性。

这只是“分配命名的属性”,没有什么比这更晦涩难懂或者更复杂甚至更“简洁”的了。

如果这听起来像一个满口,那么在整个对象结构中迭代对象属性和“设置其他属性”的实际过程并不像你想像的那样困难。

作为一个简单的例子:

 var async = require('async'), pascal = require('to-pascal-case'), mongoose = require('mongoose'), Schema = mongoose.Schema; var testSchema = new Schema({ fieldA: String, fieldB: Number }); function setStatics(schema) { Object.keys(schema.paths).filter(function(key) { return key != '_id'; }).forEach(function(key) { schema.statics['findBy' + pascal(key)] = function(arg,callback) { var query = {}; query[key] = arg; this.findOne(query,callback); }; }); }; // Set up findByFieldName other than _id setStatics(testSchema); var Test = mongoose.model( 'Test', testSchema, "test" ); mongoose.connect('mongodb://localhost/test'); async.series( [ function(callback) { Test.remove({},callback); }, function(callback) { Test.create([ { "fieldA": "a", "fieldB": 1 }, { "fieldA": "b", "fieldB": 2 } ],callback); }, function(callback) { Test.findByFieldA("a",function(err,doc) { console.log(doc); callback(err); }); }, function(callback) { Test.findByFieldB(2,function(err,doc) { console.log(doc); callback(err); }); } ], function(err) { if (err) throw err; mongoose.disconnect(); } ); 

这certificate他们通过“testing他们”的输出来工作:

 { _id: 55f2ae1b7d8315f40b1a2b77, fieldA: 'a', fieldB: 1, __v: 0 } { _id: 55f2ae1b7d8315f40b1a2b78, fieldA: 'b', fieldB: 2, __v: 0 } 

这就是它的全部。

当然,像“数组”这样的领域,你想要多一点参与,但这是作为一个列表的基本前提,你可以尝试自己(或自我为社区)。

我也可以注意到已经有一些事情,比如Bluebird通过它自己的.promisifyAll()调用,它与对象进行交互,以类似的方式在对象上设置新的“命名方法”。 或者至less它原则上应该是相似的,因为我没有真正看过这个代码。