Структура файла проекта Mongoose & NodeJS
В настоящее время у меня есть все мои модели (определения схемы) в файле /models/models.js для моего приложения Mongoose/NodeJS.
Я хотел бы разбить их на разные файлы: 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". *
Мысли?
Ответы
Ответ 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
Другими словами, определите как схему, так и модель в модуле модели, а затем экспортируйте только модель. Загрузите модули модели в свои модули контроллера, используя относительные требуемые пути.
Чтобы сделать соединение, обработайте его на раннем этапе запуска вашего сервера (server.js
или что-то еще). Обычно вам нужно будет прочитать параметры подключения либо из файла конфигурации, либо из переменных среды, и по умолчанию использовать режим развития localhost, если конфигурация не предоставляется.
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost');
Ответ 2
Пара ответов здесь действительно помогла мне разработать альтернативный подход. Исходный вопрос заключается в том, что он разбивает только определение схемы, но я предпочитаю связывать определения Схемы и Модели в том же файле.
Это в основном идея Питера, только экспорт определения модели путем переопределения 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'});
Не забудьте вызвать mongoose.connect(..) в server.js или где бы вы ни считали нужным!
Ответ 3
Недавно я ответил на вопрос Quora относительно этой же проблемы.
http://qr.ae/RoCld1
То, что я нашел очень красивым и экономит на количестве вызовов require, состоит в том, чтобы структурировать ваши модели в один каталог. Убедитесь, что у вас есть только одна модель для каждого файла.
Создайте файл index.js в том же каталоге, что и ваши модели. Добавьте сюда этот код. Обязательно добавьте необходимые fs require
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