web-dev-qa-db-ja.com

MongooseおよびNode JSプロジェクトのファイル構造

現在、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"のスキーマが登録されていません。*

考え?

57
Donn Felker

サンプル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

つまり、モデルモジュールでスキーマとモデルの両方を定義し、モデルのみをエクスポートします。相対要求パスを使用して、モデルモジュールをコントローラーモジュールに読み込みます。

接続を確立するには、サーバー起動コード(server.jsなど)の早い段階で処理します。通常、構成ファイルまたは環境変数のいずれかから接続パラメーターを読み取り、構成が提供されない場合はデフォルトで開発モードlocalhostを使用します。

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');
94
Peter Lyons

ここでのいくつかの回答は、私が代替アプローチを開発するのに本当に役立ちました。元の質問は、justスキーマ定義の破壊に関するものですが、スキーマとモデルの定義を同じファイルにバンドルすることを好みます。

これはほとんど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(..)を呼び出すことを忘れないでください。他の適切な場所で呼び出すこともできます。

35
Nick Boyle

私は最近、この同じ問題に関するQuoraの質問に回答しました。 http://qr.ae/RoCld1

私が非常にすてきで、require呼び出しの量を節約できるのは、モデルを単一のディレクトリに構造化することです。ファイルごとにモデルが1つだけであることを確認してください。

モデルと同じディレクトリに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);
  }
});

これで、すべてのモデルを次のように呼び出すことができます。

var models = require('./path/to/models');
var User = models.user;
var OtherModel = models['other-model'];
12
Josh Hardy

ピーター・ライオンズはその基盤をほとんどカバーしました。
上記の例からの借用(スキーマの後の行の削除)追加したいのは次のとおりです。

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
8
user1460015

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: {
    }
};
1
Varun Kumar