我是在一个函数能够根据情况搜索不同字段的情况下。
它返回相同的数据集,只搜索不同的字段:userId或tagId。因此,在我的代码中我有这样的东西:
var findByMethod;
if (searchBy === 'userId') {
findByMethod = UserArticleModel.findByUser;
}
else {
findByMethod = UserArticleModel.findByTag;
}
findByMethod(idToSearch, function (err, articles) {…});
findByUser
和findByTag
是UserArticleModel.js
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) {…});
一切顺利,事情顺利。但是当我通过变量动态调用方法时:
findByMethod(idToSearch, function (err, articles) {…});
当节点返回错误时出现问题:
DOMAINE ERROR CAUGHT: TypeError: Object #<Object> has no method 'find'
我怀疑this
不能被约束到正确的范围,但我不能理解为什么findByMethod === UserArticleModel.findByUser // true
答案 0 :(得分:1)
我认为你需要做的更多参与。虽然它很容易陷入“#34;太字面上”#34;以下记录的API示例和基本上&#34;这就是我需要对此进行硬编码的方式,因为文档说这就是你如何做到的#34; 。
JavaScript对象是&#34;对象&#34;,因此只是分配&#34;命名&#34;实际上只是对象属性的静态方法只是一个基本过程循环&#34;已定义的&#34;架构路径&#34;从已定义的&#34;对象&#34;并设置&#34; findByFieldName&#34;的属性;你想要的方法。
它只是&#34;分配命名属性&#34;没有什么比这更模糊或更复杂,甚至更像是&#34;简洁&#34;不止于此。
如果那个&#34;听起来像一个满口的&#34; 那么迭代对象属性的实际过程和&#34;设置其他属性&#34;与整体对象结构相关的内容并不像你想象的那么难。
作为一个简短的例子:
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();
}
);
这证明他们通过&#34;测试他们&#34;输出:
{ _id: 55f2ae1b7d8315f40b1a2b77, fieldA: 'a', fieldB: 1, __v: 0 }
{ _id: 55f2ae1b7d8315f40b1a2b78, fieldA: 'b', fieldB: 2, __v: 0 }
这就是它的全部内容。
当然对于&#34; Arrays&#34;等领域你希望得到更多的参与,但这是一个基本的前提,你可以自己尝试一下(或者一般社区自我)。
我还可以注意到,已经存在一些问题,例如Bluebird通过它自己的.promisifyAll()
调用,它与对象进行交互以设置新的&#34;命名方法& #34;以类似的方式对象。或者至少它原则上应该是相似的,因为我实际上没有看过那段代码。