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

Jon*_*Red 9 mongoose mongodb 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;
Run Code Online (Sandbox Code Playgroud)

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

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

我的单元测试都在模式模块中工作.

当我npm安装此模块并尝试创建使用

Entrepreneur = db.model('Entrepreneur', entrepreneurSchema),
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

TypeError:未定义的类型paths.mentors 您是否尝试嵌套模式?您只能使用refs或数组进行嵌套.

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

我很确定它没有像以前那样破坏,但我已经退出了所有的变化,但仍然无法正常工作.

我正在画一个完整的空白,任何建议都会感激不尽.

编辑:

我已经创建了一个新的Schemas模块.它有一个架构:

var mongoose = require('mongoose');

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

module.exports = userSchema;
Run Code Online (Sandbox Code Playgroud)

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

在OS X上运行

Bri*_*len 8

我个人使用init方法创建单独的"common"项目,用mongodb注册所有模型,并在需要访问模型的任何应用程序的app.js文件中调用init方法.

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

    "main": "index.js"
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加模型 - models在共享项目中创建一个新文件夹,以包含所有mongoose模式和插件.将userSchema文件添加到models文件夹并为其命名user.js.

    var mongoose = require('mongoose');
    
    var userSchema = new mongoose.Schema({
        email: String
    });
    
    module.exports = mongoose.model('User', userSchema);
    
    Run Code Online (Sandbox Code Playgroud)
  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;
    
    Run Code Online (Sandbox Code Playgroud)
  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);
    
    Run Code Online (Sandbox Code Playgroud)
  7. 在您的应用程序中的任何位置使用该模型 - 现在,mongoose已建立连接池并且已注册模型,您可以将模型用于应用程序中的任何类.例如,假设您有一个页面显示有关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}});
        });
    });
    
    Run Code Online (Sandbox Code Playgroud)

编辑 抱歉,我没有看到你从另一个继承一个模式的行.正如其他答案所述,mongoose已经提供了a的概念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.
}
Run Code Online (Sandbox Code Playgroud)

在您的公共模块中,在'/models/entrepreneur.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);
Run Code Online (Sandbox Code Playgroud)

  • 我不知道这在当时是否有效,但今天,如果您传入“mongoose”模块并对它执行“.connect()”,则连接将是该模块的本地连接。因此,您在 models 目录中定义的模型需要另一个“猫鼬”,但这个未连接。因此,模型在您在“init”中传递的猫鼬上不可用。 (2认同)