Mongoose & NodeJS 项目文件结构
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9230932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
File Structure of Mongoose & NodeJS Project
提问by Donn Felker
I currently have all my models (Schema definitions) in the /models/models.js file for my Mongoose/NodeJS application.
我目前在我的 Mongoose/NodeJS 应用程序的 /models/models.js 文件中有我的所有模型(架构定义)。
I'd like to break these apart into different files as such: user_account.js, profile.js, etc. However I cannot seem to do so as my controllers break and report back "cannot find module" once I pull these classes apart.
我想将它们拆分为不同的文件,例如:user_account.js、profile.js 等。但是我似乎无法这样做,因为一旦我将这些类分开,我的控制器就会中断并报告“找不到模块”。
My project structure is as follows:
我的项目结构如下:
/MyProject
/controllers
user.js
foo.js
bar.js
// ... etc, etc
/models
models.js
server.js
The contents of my models.js file looks like this:
我的 models.js 文件的内容如下所示:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
mongoose.connect('mongodb://localhost/mydb');
var UserAccount = new Schema({
user_name : { type: String, required: true, lowercase: true, trim: true, index: { unique: true } },
password : { type: String, required: true },
date_created : { type: Date, required: true, default: Date.now }
});
var Product = new Schema({
upc : { type: String, required: true, index: { unique: true } },
description : { type: String, trim: true },
size_weight : { type: String, trim: true }
});
My user.js file (controller) looks like this:
我的 user.js 文件(控制器)如下所示:
var mongoose = require('mongoose'),
UserAccount = mongoose.model('user_account', UserAccount);
exports.create = function(req, res, next) {
var username = req.body.username;
var password = req.body.password;
// Do epic sh...what?! :)
}
How can I break the schema definition into multiple files and also reference it from my controller? When I do reference it (after the schema is in a new file) I get this error:
如何将架构定义分解为多个文件并从我的控制器中引用它?当我确实引用它时(在架构位于新文件中之后),我收到此错误:
*Error: Schema hasn't been registered for model "user_account".*
*错误:尚未为模型“user_account”注册架构。*
Thoughts?
想法?
回答by Peter Lyons
Here's a sample app/models/item.js
这是一个示例 app/models/item.js
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema({
name: {
type: String,
index: true
},
equipped: Boolean,
owner_id: {
type: mongoose.Schema.Types.ObjectId,
index: true
},
room_id: {
type: mongoose.Schema.Types.ObjectId,
index: true
}
});
var Item = mongoose.model('Item', ItemSchema);
module.exports = {
Item: Item
}
To load this from an item controller in app/controllers/items.jsI would do
要从项目控制器加载它,app/controllers/items.js我会这样做
var Item = require("../models/item").Item;
//Now you can do Item.find, Item.update, etc
In other words, define both the schema and the model in your model module and then export just the model. Load your model modules into your controller modules using relative require paths.
换句话说,在模型模块中定义架构和模型,然后仅导出模型。使用相对的 require 路径将模型模块加载到控制器模块中。
To make the connection, handle that early in your server startup code (server.jsor whatever). Usually you'll want to read the connection parameters either from a configuration file or from environment variables and default to development mode localhost if no configuration is provided.
要建立连接,请在服务器启动代码(server.js或其他代码)中尽早处理。通常,您需要从配置文件或环境变量中读取连接参数,如果未提供配置,则默认为开发模式 localhost。
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');
回答by Nick Boyle
A couple answers here really helped me develop an alternative approach. The original question is regarding breaking justthe Schema definition out, but I prefer to bundle the Schema and Model definitions in the same file.
这里的几个答案确实帮助我开发了一种替代方法。最初的问题是关于仅分解Schema 定义,但我更喜欢将 Schema 和 Model 定义捆绑在同一个文件中。
This is mostly Peter's idea, only exporting the model definition by overriding module.exports to make accessing the model from your controller a little less verbose:
这主要是 Peter 的想法,仅通过覆盖 module.exports 来导出模型定义,从而使从控制器访问模型变得不那么冗长:
Project layout:
项目布局:
MyProject
/controllers
user.js
foo.js
bar.js
// ... etc, etc
/models
Item.js
server.js
models/Item.js would look like:
模型/Item.js 看起来像:
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema({
name: {
type: String,
index: true
}
});
module.exports = mongoose.model('Item', ItemSchema);
// Now `require('Item.js')` will return a mongoose Model,
// without needing to do require('Item.js').Item
And you access the model in a controller, say user.js, like:
并且您在控制器中访问模型,例如 user.js,例如:
var Item = require(__dirname+'/../models/Item')
...
var item = new Item({name:'Foobar'});
Don't forget to call mongoose.connect(..) in server.js, or wherever else you deem appropriate!
不要忘记在 server.js 或其他任何你认为合适的地方调用 mongoose.connect(..) !
回答by Josh Hardy
I recently answered a Quora question with regard to this same problem. http://qr.ae/RoCld1
我最近回答了一个关于同样问题的 Quora 问题。 http://qr.ae/RoCld1
What I have found very nice and saves on the amount of requirecalls is to structure your models into a single directory. Make sure you only have a single model per file.
我发现非常好并节省了require调用量的是将模型构建到一个目录中。确保每个文件只有一个模型。
Create an index.js file in the same directory as your models. Add this code to it. Be sure to add the necessary fsrequire
在与模型相同的目录中创建一个 index.js 文件。将此代码添加到其中。一定要添加必要的fsrequire
var fs = require('fs');
/*
* initializes all models and sources them as .model-name
*/
fs.readdirSync(__dirname).forEach(function(file) {
if (file !== 'index.js') {
var moduleName = file.split('.')[0];
exports[moduleName] = require('./' + moduleName);
}
});
Now you can call all your models as follows:
现在您可以按如下方式调用所有模型:
var models = require('./path/to/models');
var User = models.user;
var OtherModel = models['other-model'];
回答by user1460015
Peter Lyons pretty much covered the basis.
Borrowing from the above example (removing the lines after the schema) I just wanted to add:
Peter Lyons 几乎涵盖了基础知识。
借用上面的例子(删除模式后面的行)我只想添加:
app/models/item.js
app/models/item.js
note: notice where `module.exports` is placed
var mongoose = require("mongoose");
var ItemSchema = module.exports = new mongoose.Schema({
name: {
type: String,
index: true
},
...
});
To load it from the app/controllers/items.js
从 app/controllers/items.js
var mongoose = require('mongoose');
var Item = mongoose.model('Item', require('../models/item'));
Another way without the module.exportsor require:
没有module.exportsor 的另一种方式require:
app/models/item.js
app/models/item.js
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema({
name: {
type: String,
index: true
},
...
});
mongoose.model('Item', ItemSchema); // register model
In the app/controllers/items.js
在里面 app/controllers/items.js
var mongoose = require('mongoose')
, Item = mongoose.model('Item'); // registered model
回答by Varun Kumar
Inspired by sequelize-cli, I have a models directory where i define all schema.
受 sequelize-cli 的启发,我有一个模型目录,我在其中定义了所有模式。
Complete app on github: https://github.com/varunon9/node-starter-app-mongo
github 上的完整应用程序:https: //github.com/varunon9/node-starter-app-mongo
models/index.js-
模型/index.js-
'use strict';
const fs = require('fs');
const path = require('path');
const mongoose = require('mongoose');//.set('debug', true);
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
const Schema = mongoose.Schema;
fs
.readdirSync(__dirname)
.filter(fileName => {
return (
fileName.indexOf('.') !== 0)
&& (fileName !== basename)
&& (fileName.slice(-3) === '.js'
);
})
.forEach(fileName => {
const model = require(path.join(__dirname, fileName));
const modelSchema = new Schema(model.schema);
modelSchema.methods = model.methods;
modelSchema.statics = model.statics;
// user.js will be user now
fileName = fileName.split('.')[0];
db[fileName] = mongoose.model(fileName, modelSchema);
});
module.exports = db;
models/user.js-
模型/user.js-
'use strict';
module.exports = {
schema: {
email: {
type: String,
required: true,
unique: true,
},
mobile: {
type: String,
required: false
},
name: {
type: String,
required: false
},
gender: {
type: String,
required: false,
default: 'male'
},
password: {
type: String,
required: true
},
dob: {
type: Date,
required: false
},
deactivated: {
type: Boolean,
required: false,
default: false
},
type: {
type: String,
required: false
}
},
// instance methods goes here
methods: {
},
// statics methods goes here
statics: {
}
};

