2012-02-10 4 views
51

В настоящее время у меня есть все мои модели (определения схемы) в файле /models/models.js для моего приложения Mongoose/NodeJS.Структура файла проекта 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

Я написал модуль мангуста-клей, который помогает структурировать ваши модели мангуста: https: // github.com/xpepermint/mongoose-glue – xpepermint

ответ

88

Вот пример 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'); 
+0

как насчет кода подключения? как включить это в отдельный код –

+4

Я обновил свой ответ, чтобы обратиться к этому вопросу. –

+2

Это было так просто? lol – ShrekOverflow

8

Peter Lyons в значительной степени покрыл основу.
заимствование из приведенного выше примера (удаление строки после схемы), я просто хотел бы добавить:

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 
+0

И откуда будут звонить контроллеры? – Warz

+0

Не уверен, что я понимаю ваш вопрос. Вы можете уточнить? – user1460015

35

пару ответов здесь действительно помогли мне развить альтернативный подход. Первоначальный вопрос касается разбиения только определение схемы, но я предпочитаю связывать определения Схемы и Модели в том же файле.

Это в основном идея Петра, только экспорт определения модели путем переопределения module.exports, чтобы сделать доступ к модели из контроллера немного компактнее:

макет проекта:

MyProject 
    /controllers 
    user.js 
    foo.js 
    bar.js 
    // ... etc, etc 
    /models 
    Item.js 
    server.js 

модели/предмета .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 или где угодно, если вы сочтете это подходящим!

9

Недавно я ответил на вопрос Quora относительно этой же проблемы. http://qr.ae/RoCld1

То, что я нашел очень хороший и экономит на количестве требуют вызовов, чтобы структурировать свои модели в единый каталог. Убедитесь, что у вас есть только одна модель для каждого файла.

Создайте файл index.js в том же каталоге, что и ваши модели. Добавьте сюда этот код. Не забудьте добавить необходимые фсов требуют

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']; 
+1

Это, безусловно, лучший ответ, автоматизация экономит много избыточности в коде, и в итоге он выглядит очень чистым. – zoubida13

+0

Я предполагаю, что у вас есть код инициализации db в корне проекта. Любая идея, как это работает? благодаря –

Смежные вопросы