外部模块中的模式在Node.js中不起作用

外部模块中的模式在Node.js中不起作用

问题描述:

我很头痛,尝试通过模块将一些常见模式定义分享给我的代码库中的所有其他模块。外部模块中的模式在Node.js中不起作用

我有一个包含这两种模式一个myproj_schemas模块:

var mongoose = require('mongoose'), 
    util = require("util"), 
    Schema = mongoose.Schema; 

var BaseProfileSchema = function() { 
    Schema.apply(this, arguments); 

    this.add({ 
     _user: {type: Schema.Types.ObjectId, ref: 'User', required: true}, 
     name: {type: String, required: true}, 
     bio: {type: String, required: true}, 
     pictureLink: String 
    }); 

}; 
util.inherits(BaseProfileSchema, Schema); 

module.exports = BaseProfileSchema; 

而且

var mongoose = require('mongoose'), 
    BaseProfileSchema = require('./base_profile_schema.js'), 
    Schema = mongoose.Schema; 

var entSchemaAdditions = { 
    mentors: {type: Schema.Types.ObjectId, ref: 'Mentor'} 
}; 


var entrepreneurSchema = new BaseProfileSchema(entSchemaAdditions); 

module.exports = entrepreneurSchema; 

导师也是在另一个文件中定义。

我的单元测试这两个工作在schemas模块。

当我NPM安装该模块并尝试使用

Entrepreneur = db.model('Entrepreneur', entrepreneurSchema), 

我收到以下错误创建:

类型错误:未定义类型在paths.mentors 你尝试筑巢的架构?您只能使用参考或数组进行嵌套。

如果我在本地模块中使用相同的代码,那么没问题。 如果我在require中直接引用模式文件(例如require('../ node_modules/myproj_schemas/models/ent_schema'),那么我会得到错误信息。

我确信它不会像这样破坏较早,但我已经备份了所有的变化,它仍然没有工作

我画一个完整的空白,并且任何建议将受到欢迎

编辑:。

我已经创建了一个新的Schemas模块,它有一个Schema:

var mongoose = require('mongoose'); 

var userSchema = new mongoose.Schema({ 
    email: String 
}); 

module.exports = userSchema; 

当打包到模块中并将npm安装到其他模块时,这也会失败。

运行在OS X

个人而言,我创建了单独的“共同”项目与init方法进行登记的所有车型的共同模式的猫鼬插件mongodb,然后在任何需要访问模型的应用程序的app.js文件中调用init方法。

  1. 创建共享项目 - 按照标​​准过程创建新节点项目。
  2. 的package.json - 在共享项目中,设置您的package.json文件包含以下项:

    "main": "index.js" 
    
  3. 添加模型 - 共享项目中创建一个新的文件夹models,以包含你所有的猫鼬模式和插件。将您的userSchema文件添加到模型文件夹并将其命名为user.js

    var mongoose = require('mongoose'); 
    
    var userSchema = new mongoose.Schema({ 
        email: String 
    }); 
    
    module.exports = mongoose.model('User', userSchema); 
    
  4. index.js - 然后在项目的根index.js文件创建可由您的应用程序一起使用,露出模型和init方法的共享对象。有许多方法来编写这一点,但这里是我如何做它:

    function Common() { 
        //empty array to hold mongoose Schemas 
        this.models = {}; 
    } 
    
    Common.prototype.init = function(mongoose) { 
        mongoose.connect('your mongodb connection string goes here'); 
        require('./models/user'); 
        //add more model references here 
    
        //This is just to make referencing the models easier within your apps, so you don't have to use strings. The model name you use here must match the name you used in the schema file 
        this.models = { 
         user: mongoose.model('User') 
        } 
    } 
    
    var common = new Common(); 
    
    module.exports = common; 
    
  5. 参考您的common项目 - 但是要引用您的共享项目中,引用添加到共享项目中package.json文件在您的应用程序中,并给它一个名称common。我个人使用GitHub来存储项目并引用存储库路径。由于我的存储库是私有的,我必须在GitHub支持站点上覆盖的路径中使用一个密钥。
  6. 初始化在您的应用程序模型 - 在你的应用程序的启动脚本(假设它是app.js在这个例子中)的引用添加到您的common项目,并调用init方法连接到MongoDB服务器和注册楷模。

    //at the top, near your other module dependencies 
    var mongoose = require('mongoose') 
        , common = require('common'); 
    
    common.init(mongoose); 
    
  7. 使用模型中的任何地方你的应用程序 - 现在,猫鼬已经建立了连接池和模型已经被注册,您可以使用这些模型是任何你的应用程序中的类的。例如,假设你有一个显示有关user的信息,你可以做这样一个网页(未经测试的代码,就写了这个为例):

    var common = require('common'); 
    
    app.get('/user-profile/:id', function(req, res) { 
        common.models.user.findById(req.params.id, function(err, user) { 
         if (err) 
          console.log(err.message); //do something else to handle the error 
         else 
          res.render('user-profile', {model: {user: user}}); 
        }); 
    }); 
    

编辑 对不起,我没看不到你从另一个模式继承一个模式的行。作为其他答案之一,猫鼬已经提供了plugin的概念。在你上面的例子,你可以这样做:

在您的通用模块,在“/models/base-profile-plugin.js”

module.exports = exports = function baseProfilePlugin(schema, options){ 

    //These paths will be added to any schema that uses this plugin 
    schema.add({ 
     _user: {type: Schema.Types.ObjectId, ref: 'User', required: true}, 
     name: {type: String, required: true}, 
     bio: {type: String, required: true}, 
     pictureLink: String 
    }); 

    //you can also add static or instance methods or shared getter/setter handling logic here. See the plugin documentation on the mongoose website. 
} 

在您的通用模块,在“/型号/企业家.js文件

var mongoose = require('mongoose') 
    , basePlugin = require('./base-profile-plugin.js'); 

var entrepreneurSchema = new mongoose.Schema({ 
    mentors: {type: Schema.Types.ObjectId, ref: 'Mentor'} 
}); 

entrepreneurSchema.plugin(basePlugin); 

module.exports = mongoose.model('Entrepreneur', entrepreneurSchema); 
+0

感谢这样一个完整的答案。由于有这个问题,我更多地转向这种类型的解决方案,它不需要我在模块之间共享模式。我仍然不清楚为什么会出现问题,但我开始认为这是环境问题,也许一些缓存清理会有所帮助。 – JonRed 2014-11-20 17:37:25

+0

我打算接受这个答案 - 并不是因为它直接回答我的问题,而是因为我认为它将*别服务于社区。再次感谢您的努力。 – JonRed 2014-11-20 17:38:16

+0

我没有真正得到这个工作,并且不得不使用'proxyquire'来覆盖我的模式定义模块中使用的Mongoose实例。工程,但似乎很肮脏。 – Mikke 2015-01-28 10:59:01

你基本上找的是对模式的继承,有一个叫猫鼬伸出,实际上解决您的问题的项目,你可以决定是否要实现它还是去看一下代码,做你自己的。

刚刚安装USNG NPM

$ npm install mongoose-schema-extend 

这是它如何工作的:

var mongoose = require('mongoose'), 
    extend = require('mongoose-schema-extend'); 
var Schema = mongoose.Schema; 

var PersonSchema = new Schema({ 
    name : String 
}, { collection : 'users' }); 

var EmployeeSchema = PersonSchema.extend({ 
    department : String 
}); 

var Person = mongoose.model('Person', PersonSchema), 
    Employee = mongoose.model('Employee', EmployeeSchema); 

var Brian = new Employee({ 
    name : 'Brian Kirchoff', 
    department : 'Engineering' 
}); 

问候

+0

这是一个非常有用的答案,但没有解决问题。在编辑中,您可以看到我遇到了非扩展架构的问题。我越来越确信,这个问题是环境问题,但没有机会在另一台机器上证明它。 – JonRed 2014-11-20 17:32:57