2015-09-11 3 views
1

Я в том случае, когда функция может выполнять поиск по различным полям в зависимости от ситуации.Определение методов модели мануата Динамически

Он возвращает тот же набор данных, он просто ищет различные поля: либо 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

Хорошо, проблема заключается в том, как вы реализуете код для их создания, что также не та часть, которую вы показываете. Но в качестве базового принципа, чтобы установить их, вы, в основном, «циклично выполняете» поля, присутствующие в схеме, и называете: userArticleSchema.statics [fieldName] = function (arg, callback) {var query = {}; query [fieldName] = arg; this.findOne (query, function (err, doc) {... 'и т. д. Где вы должны получить общий смысл. Все JavaScript - это просто объекты. –

+0

Если это не опечатка в вопросе, тогда' userArticleSchema.staticsfindByTag' является вашим реальная проблема «опечатки», когда вы забыли точку ».« –

+0

Это была опечатка в вопросе, я исправил ее. thx – Buzut

ответ

1

Я думаю, вы делаете это более привлекательным, что нужно. Хотя это легкая ловушка, которая попадает под «слишком буквально» после документированных примеров API и, по существу, мышления «вот как мне нужно жестко закодировать это, потому что документы говорят, что это так, как вы это делаете».

Объекты JavaScript, ну и «Объекты», и поэтому просто присваивание статическим методам «named», которые на самом деле являются только объектными свойствами, является всего лишь базовым процессом «циклизации» определенных «путей схемы» из уже определенного «объекта», и настройки свойств для методов «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(); 
    } 
); 

Что доказывает, что они работают «их тестирования» с выходом:

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

И это все есть на него.

Конечно, для таких полей, как «Массивы», вы хотите немного поработать, но это основная предпосылка, поскольку вы можете попробовать себя (или себя для сообщества в целом).

Я также мог бы отметить, что есть уже несколько вещей, таких как Bluebird через свой собственный вызов .promisifyAll(), который взаимодействует с объектами, чтобы установить новые «именованные методы» на объекте аналогичным образом.Или, по крайней мере, это должно быть похоже в принципе, поскольку я на самом деле не смотрел на этот код.

+0

Это очень приятно! Большое спасибо. – Buzut

+1

@Buzut Как предупреждают, это «ov упрощенно "для использования в целом, но иллюстрирует концепции. Уже думая, что бит поиска не соответствует чему-то подобному, тогда немного времени может привести к тому, что опубликованный пакет будет намного более полным. В конце концов, я знаю, что такие вещи, как «grails», устанавливают по умолчанию такие методы. И, по крайней мере, это также побудило меня снять голос за закрытие/удержание из-за первоначального подозрения, что это в основном опечатки. «Вопрос» со всем пониманием того, что вы пытались достичь, на самом деле полезен. –

+0

Я принял к сведению, что это не производство, но оно вдохновляет! Я уверен, что модуль npn будет действительно полезен. – Buzut

Смежные вопросы