外部模块中的架构在Node.js中不起作用 [英] Schemas in external module not working in Node.js
问题描述
我非常想通过一个模块与我代码库中的所有其他模块共享一些通用的架构定义.
I'm having a massive headache try to share some common schema definitions via a module to all the other modules in my code base.
我有一个myproj_schemas模块,其中包含以下两种模式:
I have a myproj_schemas module that contains these two 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;
导师也定义在另一个文件中.
Mentors is also defined in another file.
我的单元测试都可以在schemas模块中完成这两项工作.
My unit tests for these both work in the schemas module.
当我npm安装此模块并尝试使用创建时
When I npm install this module and try to create using
Entrepreneur = db.model('Entrepreneur', entrepreneurSchema),
我收到以下错误:
TypeError:paths.mentors
处的类型不确定
您是否尝试过嵌套架构?您只能使用引用或数组进行嵌套.
TypeError: Undefined type at paths.mentors
Did you try nesting Schemas? You can only nest using refs or arrays.
如果我在本地模块中使用相同的代码,则没有问题. 如果我直接在require中引用架构文件(例如require('../node_modules/myproj_schemas/models/ent_schema'),那么我会收到错误消息.
If I use the same code in my local module, then no problem. If I reference the schema file directly in the require (e.g. require('../node_modules/myproj_schemas/models/ent_schema') then I get the error.
我相当确定它不会像以前那样中断,但是我已经撤消了所有更改,但仍然无法正常工作.
I'm fairly sure it wasn't breaking like this earlier, but I've backed out all the changes and it is still not working.
我正在绘制一个完整的空白,将不胜感激地收到任何建议.
I'm drawing a complete blank, and any suggestions would be gratefully received.
我创建了一个新的Schemas模块.它具有一个模式:
I've created a new Schemas module. It has one Schema:
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
email: String
});
module.exports = userSchema;
当打包到一个模块中并且将npm安装到其他模块时,这也会失败.
This also fails when packaged up in a module and npm install'd to other modules.
在OS X上运行
推荐答案
我个人使用init方法创建了一个单独的"common"项目,以使用mongodb注册所有模型,并在的app.js文件中调用init方法.需要访问模型的所有应用.
Personally I created separate "common" project with an init method to register all of the models with mongodb, and call the init method in the app.js file of any apps that need access to the models.
- 创建共享项目-按照标准流程创建新的节点项目.
-
package.json -在共享项目中,将您的
package.json
文件设置为包含以下条目:
- Create a shared project - Create a new node project, following the standard process.
package.json - In the shared project, set your
package.json
file to contain the following entry:
"main": "index.js"
添加模型-在共享项目中创建一个新的models
文件夹,其中包含所有猫鼬模式和插件.将您的userSchema文件添加到models文件夹并将其命名为user.js
.
Add a model - Create a new models
folder within your shared project, to contain all of your mongoose schemas and plugins. Add your userSchema file to the models folder and name it user.js
.
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
email: String
});
module.exports = mongoose.model('User', userSchema);
index.js -然后在项目的根index.js
文件中创建一个共享对象,供您的应用使用,公开模型和init
方法.有很多方法可以对此进行编码,但是这是我的操作方式:
index.js - Then in the project's root index.js
file create a shared object that can be used by your apps, exposing the models and an init
method. There's many ways to code this, but here's how I'm doing it:
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;
common
项目-但是,您想引用共享项目,请将引用添加到应用程序内package.json
文件中的共享项目中,并将其命名为 在您的应用程序中初始化模型-在您的应用程序的启动脚本中(假设此示例为app.js
),将引用添加到您的common
项目并调用init
方法连接到mongodb服务器并注册模型.
common
project - However you want to reference your shared project, add the reference to the shared project in the package.json
file within your app and give it a name of common
. Personally I used GitHub to store the project and referenced the repository path. Since my repository was private I had to use a key in the path, which is covered on the GitHub support site.Init the models in your app - In the start script for your app (let's assume it's app.js
for this example) add the reference to your common
project and call the init
method to connect to the mongodb server and register the models.
//at the top, near your other module dependencies
var mongoose = require('mongoose')
, common = require('common');
common.init(mongoose);
在应用程序中的任何位置使用模型-既然mongoose已经建立了连接池并且已经注册了模型,则可以使用模型中的任何模型.例如,假设您有一个页面显示有关user
的信息,则可以这样操作(未经测试的代码,仅为示例编写):
Use the model anywhere in your app - Now that mongoose has the connection pool established and the models have been registered, you can use the models is any of the classes within your app. For example, say you have a page that displays information about a user
you could do it like this (untested code, just wrote this for an example):
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
的概念.在上面的示例中,您将执行以下操作:
EDIT
Sorry, I didn't see the line where you were inheriting one schema from another. As one of the other answers stated, mongoose already offers the concept of a plugin
. In your example above, you would do this:
在您的通用模块中的"/models/base-profile-plugin.js"下
In your common module, under '/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.
}
在您的通用模块的'/models/entrepreneur.js
In your common module, under '/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);
这篇关于外部模块中的架构在Node.js中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!