在单独的模块中定义 Mongoose 模型

Posted

技术标签:

【中文标题】在单独的模块中定义 Mongoose 模型【英文标题】:Defining Mongoose Models in Separate Module 【发布时间】:2012-04-15 04:08:06 【问题描述】:

我想将我的 Mongoose 模型分离到一个单独的文件中。我试图这样做:

var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var Material = new Schema(
    name                :    type: String, index: true,
    id                  :    ObjectId,
    materialId          :    String,
    surcharge           :    String,
    colors              :    
        colorName       :    String,
        colorId         :    String,
        surcharge       :    Number
    
);

var SeatCover = new Schema(
    ItemName            :    type: String, index: true,
    ItemId              :    ObjectId,
    Pattern             :    String,
    Categories          :    
        year            :    type: Number, index: true,
        make            :    type: String, index: true,
        model           :    type: String, index: true,
        body            :    type: String, index: true
    ,
    Description         :    String,
    Specifications      :    String,
    Price               :    String,
    Cost                :    String,
    Pattern             :    String,
    ImageUrl            :    String,
    Materials           :    [Materials]
);

mongoose.connect('mongodb://127.0.0.1:27017/sc');

var Materials = mongoose.model('Materials', Material);
var SeatCovers = mongoose.model('SeatCover', SeatCover);

exports.Materials = Materials;
exports.SeatCovers = SeatCovers;

然后,我尝试使用这样的模型:

var models = require('./models'); 

exports.populateMaterials = function(req, res)
    console.log("populateMaterials");
    for (var i = 0; i < materials.length; i++ )
        var mat = new models.Materials();
        console.log(mat);
        mat.name = materials[i].variantName;
        mat.materialId = materials[i].itemNumberExtension;
        mat.surcharge = materials[i].priceOffset;
        for (var j = 0; j < materials[i].colors.length; j++)
            mat.colors.colorName = materials[i].colors[j].name;
            mat.colors.colorId = materials[i].colors[j].itemNumberExtension;
            mat.colors.surcharge = materials[i].colors[j].priceOffset;
        
        mat.save(function(err)
            if(err)
                console.log(err);
             else 
                console.log('success');
            
        );
    
    res.render('index',  title: 'Express' );
;

这是在单独模块中引用模型的合理方法吗?

【问题讨论】:

应该是[Material] 而不是[Materials],不是吗? 不是,Materials 是 Model 的名字,是 Schema 引用的。 Material 只是一个局部变量的名称。 【参考方案1】:

我喜欢在模型文件之外定义数据库,以便可以使用 nconf 进行配置。另一个优点是您可以在模型之外重用 Mongo 连接。

module.exports = function(mongoose) 
    var Material = new Schema(
        name                :    type: String, index: true,
        id                  :    ObjectId,
        materialId          :    String,
        surcharge           :    String,
        colors              :    
            colorName       :    String,
            colorId         :    String,
            surcharge       :    Number
        
    );
    // declare seat covers here too
    var models = 
      Materials : mongoose.model('Materials', Material),
      SeatCovers : mongoose.model('SeatCovers', SeatCover)
    ;
    return models;

然后你会这样称呼它......

var mongoose = require('mongoose');
mongoose.connect(config['database_url']);
var models = require('./models')(mongoose);
var velvet = new models.Materials('name':'Velvet');

【讨论】:

这种方法+1。我个人自己使用它,并认为我是唯一的一个。很高兴终于看到我从一开始就在做某事。 你不必在模型文件中使用 createConnection 吗? 不,实际上我认为如果你不这样做会更好。模型需要一个猫鼬对象,这就是他们所关心的。最好将连接管理放在一个地方并“注入”猫鼬对象。这是配置管理和代码重用的最佳实践。 您甚至不必将 mongoose 传递给模型模块来执行此操作。只需直接拥有模型模块require('mongoose');。我什至在单独的文件(模块)中定义每个模型模式和特殊功能,并且每个都导出它自己的模型。另外我认为mongoose.model('ModelName') 将在您使用mongoose.model('ModelName', Schema) 定义模型后随时返回模型 @GabrielLittman 我也是这样做的,它可以工作,但是从 mongoose 官方文档中,您必须使用相同的 mongoose 实例来定义和检索模型【参考方案2】:

基本方法看起来很合理。

作为一个选项,您可以考虑集成模型和控制器功能的“提供者”模块。这样,您可以让 app.js 实例化提供程序,然后所有控制器功能都可以由它执行。 app.js 只需指定要实现的具有相应控制器功能的路由。

为了进一步整理,您还可以考虑将路由分支到一个单独的模块中,并使用 app.js 作为这些模块之间的粘合剂。

【讨论】:

github.com/cmarin/MongoDB-Node-Express-Blog 是上述概念的良好实现。 有趣的想法@aimypal。我想做和 rob_hicks 一样的事情。不过我很好奇,我正在查看您提供的 git 链接上的代码,并且想知道如果我们通过简单地将这些方法添加到 Post.statics 来替换 PostProvider 是否会更好。我想它会有同样的结果? 不同的方法。但是发现这个组织得非常好。

以上是关于在单独的模块中定义 Mongoose 模型的主要内容,如果未能解决你的问题,请参考以下文章

在客户端代码中重用 Mongoose 模式

mongoose 模型连接到 mongoDB

mongoose 模型连接到 mongoDB

在单独的文件中对 Mongoose 模型进行单元测试会导致问题(使用 Mockgoose & Lab)

Mongoose:检查对象是不是为猫鼬对象

node21---mongoose