2012-02-10 15 views
51

Actualmente tengo todos mis modelos (definiciones de esquema) en el archivo /models/models.js para mi aplicación Mongoose/NodeJS.Estructura de archivo de Mongoose & NodeJS Project

me gustaría romper estos aparte en diferentes archivos, tales como: user_account.js, profile.js, etc. Sin embargo, me parece que no puede hacerlo como mis controladores rompen e informar "no puede encontrar el módulo" una vez Hago estas clases aparte.

Mi estructura del proyecto es el siguiente:

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

El contenido de mi archivo models.js se ve así:

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 } 
}); 

Mi archivo user.js (controlador) tiene el siguiente aspecto:

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?! :) 
} 

¿Cómo puedo dividir la definición del esquema en varios archivos y también hacer referencia a él desde mi contro ller? Cuando hago referencia a ella (después de que el esquema es en un nuevo archivo) me sale este error:

* Error: el esquema no se ha registrado para el modelo "USER_ACCOUNT" *

pensamientos.?

+1

escribí módulo mangosta-pegamento que ayuda a estructurar sus modelos mangosta: https: // github.com/xpepermint/mongoose-glue – xpepermint

Respuesta

88

He aquí una muestra 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 
} 

Para cargar esto desde un controlador de elemento en app/controllers/items.js lo haría

var Item = require("../models/item").Item; 
    //Now you can do Item.find, Item.update, etc 

En otras palabras, definir tanto el esquema y el modelo en su módulo de modelo y luego exporta solo el modelo. Cargue los módulos de su modelo en sus módulos de controlador utilizando rutas de acceso relativas.

Para realizar la conexión, gestione eso al principio del código de inicio del servidor (server.js o lo que sea). Por lo general, querrá leer los parámetros de conexión desde un archivo de configuración o desde variables de entorno y de forma predeterminada a modo de desarrollo localhost si no se proporciona ninguna configuración.

var mongoose = require('mongoose'); 
mongoose.connect('mongodb://localhost'); 
+0

¿qué pasa con el código de conexión? cómo incluir eso en un código separado –

+4

Actualicé mi respuesta para abordar ese punto. –

+2

¿Fue así de simple? lol – ShrekOverflow

8

Peter Lyons prácticamente cubrió la base.
préstamos del ejemplo anterior (eliminación de las líneas después el esquema) sólo quería añadir:

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 
    }, 
    ... 

}); 

que cargarlo desde el app/controllers/items.js

var mongoose = require('mongoose'); 
var Item = mongoose.model('Item', require('../models/item')); 

Otra forma sin el module.exports o 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 

En los app/controllers/items.js

var mongoose = require('mongoose') 
    , Item = mongoose.model('Item'); // registered model 
+0

¿Y desde dónde se llamarán los controladores? – Warz

+0

No estoy seguro de entender su pregunta. ¿Puedes aclarar? – user1460015

35

Un par de respuestas aquí realmente me ayudó a desarrollar un enfoque alternativo. La pregunta original se refiere a romper solo la definición de Esquema, pero prefiero agrupar las definiciones de Esquema y Modelo en el mismo archivo.

Esto es sobre todo la idea de Peter, solamente la exportación de la definición del modelo reemplazando module.exports para facilitar el acceso al modelo de su controlador de un poco menos detallado:

diseño del proyecto:

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

modelos/artículo Js se vería así:

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 

Y tener acceso al modelo de un controlador, dicen user.js, como:

var Item = require(__dirname+'/../models/Item') 

... 

var item = new Item({name:'Foobar'}); 

¡No olvide llamar a mongoose.connect (..) en server.js, o donde lo considere apropiado!

9

Recientemente he respondido una pregunta de Quora con respecto a este mismo problema. http://qr.ae/RoCld1

Lo que he encontrado muy agradable y lo guarda en la cantidad de requieren llamadas es estructurar sus modelos en un solo directorio. Asegúrese de tener solo un modelo por archivo.

Cree un archivo index.js en el mismo directorio que sus modelos. Agregue este código a él. Asegúrese de añadir los fs necesarias requieren

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); 
    } 
}); 

Ahora puede llamar a todos los modelos de la siguiente manera:

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

Esta es, de lejos, la mejor respuesta, la automatización ahorra mucha redundancia en el código y termina pareciendo muy limpio. – zoubida13

+0

Supongo que tiene su código de inicialización de db en la raíz del proyecto. ¿Alguna idea de cómo funciona esto? Gracias –

Cuestiones relacionadas