Mongoose 和 Node JS 项目的文件结构
Posted
技术标签:
【中文标题】Mongoose 和 Node JS 项目的文件结构【英文标题】:File Structure of Mongoose & NodeJS Project 【发布时间】:2012-03-03 02:36:01 【问题描述】:目前,我的 Mongoose/NodeJS 应用程序的 /models/models.js 文件中包含我的所有模型(架构定义)。
我想将它们分成不同的文件,例如:user_account.js、profile.js 等。但是我似乎无法这样做,因为我的控制器中断并报告“找不到模块强>”一旦我把这些类分开。
我的项目结构如下:
/MyProject
/controllers
user.js
foo.js
bar.js
// ... etc, etc
/models
models.js
server.js
我的 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
);
我的 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?! :)
如何将架构定义分解为多个文件并从我的控制器中引用它?当我确实引用它时(在架构位于新文件中之后)我收到此错误:
*错误:尚未为模型“user_account”注册架构。*
想法?
【问题讨论】:
我写了 mongoose-glue 模块来帮助构建你的 mongoose 模型:github.com/xpepermint/mongoose-glue 【参考方案1】:这是一个示例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
要从 app/controllers/items.js
中的项目控制器加载它,我会这样做
var Item = require("../models/item").Item;
//Now you can do Item.find, Item.update, etc
换句话说,在模型模块中定义模式和模型,然后只导出模型。使用相对的 require 路径将模型模块加载到控制器模块中。
要建立连接,请在服务器启动代码的早期处理它(server.js
或其他)。通常你会希望从配置文件或环境变量中读取连接参数,如果没有提供配置,则默认为开发模式 localhost。
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');
【讨论】:
连接码呢?如何将其包含在单独的代码中 这仍然是一个有效的解决方案吗? @PeterLyons @taco 由于已编译的模型缓存,我在使用此解决方案时遇到问题:OverwriteModelError
(v3.8.17 中的猫鼬/lib/index.js@@334)。建议的解决方法是设置var ItemSchema = mongoose.modelSchemas['Item'] || new mongoose.Schema(...);
(对我有用)
你为什么要定义你的模式两次?该代码应该每个进程只运行一次。
当模式被编译时,它会添加一些额外的东西(_events 对象和 __virtual 和其他一些东西),所以在 index.js 与缓存模式的比较中,它与OverwriteModelError
相比失败了。每次请求模块时都会传递架构,我不知道为什么,也许它是一个调试功能或者我仍然没有找到原因......(模块的实现方式与您在此处提出的相同方式只是更改名称和字段)【参考方案2】:
这里的几个答案确实帮助我开发了另一种方法。最初的问题是关于打破just Schema 定义,但我更喜欢将 Schema 和 Model 定义捆绑在同一个文件中。
这主要是 Peter 的想法,仅通过覆盖 module.exports 来导出模型定义,以使从控制器中访问模型变得不那么冗长:
项目布局:
MyProject
/controllers
user.js
foo.js
bar.js
// ... etc, etc
/models
Item.js
server.js
models/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
然后你在控制器中访问模型,比如 user.js,比如:
var Item = require(__dirname+'/../models/Item')
...
var item = new Item(name:'Foobar');
不要忘记在 server.js 或其他您认为合适的地方调用 mongoose.connect(..)!
【讨论】:
【参考方案3】:我最近回答了一个关于这个问题的 Quora 问题。 http://qr.ae/RoCld1
我发现非常好的并节省 require 调用量的方法是将模型构建到单个目录中。确保每个文件只有一个模型。
在与模型相同的目录中创建一个 index.js 文件。将此代码添加到其中。请务必添加必要的 fs 要求
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);
);
现在您可以按如下方式调用所有模型:
var models = require('./path/to/models');
var User = models.user;
var OtherModel = models['other-model'];
【讨论】:
这是迄今为止最好的答案,自动化在代码中节省了大量冗余,而且最终看起来非常干净。 我假设你在项目根目录中有你的数据库初始化代码。知道这是如何执行的吗?谢谢【参考方案4】:彼得里昂几乎涵盖了基础。 借用上面的例子(删除模式后的行)我只想添加:
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
,
...
);
从app/controllers/items.js
加载它
var mongoose = require('mongoose');
var Item = mongoose.model('Item', require('../models/item'));
没有module.exports
或require
的另一种方式:
app/models/item.js
var mongoose = require("mongoose");
var ItemSchema = new mongoose.Schema(
name:
type: String,
index: true
,
...
);
mongoose.model('Item', ItemSchema); // register model
在app/controllers/items.js
var mongoose = require('mongoose')
, Item = mongoose.model('Item'); // registered model
【讨论】:
从哪里调用控制器? 不确定我是否理解您的问题。你能澄清一下吗?【参考方案5】:受 sequelize-cli 的启发,我有一个模型目录,我在其中定义了所有模式。
github上的完整应用:https://github.com/varunon9/node-starter-app-mongo
models/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-
'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:
;
【讨论】:
【参考方案6】:我喜欢用类来组织一切,不妨试试这个:
const mongoose = require('mongoose')
class UserAccount
constructor()
this.schema = new mongoose.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
);
this.model = new mongoose.model('UserAccount', this.schema)
create = (obj) =>
return new Promise((resolve, reject) =>
this.model.create( ...item )
.then((result) =>
resolve(result)
).catch((err) =>
reject(err)
);
);
module.exports = UserAccount;
这种方法允许您添加自定义方法。此外,它将控制器/模型组合成一个向量,允许您随时分离模型。这可能无法在企业中扩展,但它可能适合较小的应用程序。
【讨论】:
以上是关于Mongoose 和 Node JS 项目的文件结构的主要内容,如果未能解决你的问题,请参考以下文章
vue+mongoose+node.js项目总结第一篇_图片文件上传
不能使用 Node js(express) 和 MongoDB(mongoose) 对用户配置文件进行审核
Node.js/Mongoose/MongoDb Typescript MapReduce - emit() 和 Array.sum() 方法
Node.js/Mongoose/MongoDb Typescript MapReduce - emit() 和 Array.sum() 方法