2012-02-10 17 views
51

Attualmente ho tutti i miei modelli (definizioni dello schema) nel file /models/models.js per l'applicazione Mongoose/NodeJS.Struttura file del progetto Mongoose & NodeJS

vorrei rompere questi pezzi in file diversi, come ad esempio: user_account.js, profile.js, ecc, tuttavia io non riesco a farlo da violano i miei regolatori e di riferire "non riesce a trovare il modulo" una volta Io divario queste classi.

La mia struttura del progetto è la seguente:

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

Il contenuto del mio file models.js aspetto:

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

Il mio file user.js (controllore) si presenta così:

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

Come posso rompere la definizione dello schema in più file e farvi riferimento anche dal mio contro ller? Quando faccio riferimento a esso (dopo lo schema è in un nuovo file) ottengo questo errore:

* Errore: schema non è stato registrato per il modello "user_account" *

pensieri.?

+1

ho scritto modulo mangusta-collante che aiuta a strutturare i vostri modelli mangusta: https: // github.com/xpepermint/mongoose-glue – xpepermint

risposta

88

Ecco un esempio 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 
} 

Per caricare questo da un controller elemento in app/controllers/items.js avrei fatto

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

In altre parole, definire sia lo schema e il modello in vostro modulo di modello e quindi esporta solo il modello. Caricare i moduli del modello nei moduli del controller utilizzando percorsi di richiesta relativi.

Per effettuare la connessione, gestirla in anticipo nel codice di avvio del server (server.js o qualsiasi altra cosa). In genere, è necessario leggere i parametri di connessione da un file di configurazione o da variabili di ambiente e, in caso di configurazione predefinita, in modalità di sviluppo localhost, se non viene fornita alcuna configurazione.

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

E il codice di connessione? come includerlo in un codice separato –

+4

Ho aggiornato la mia risposta per risolvere quel punto. –

+2

Era così semplice? lol – ShrekOverflow

8

Peter Lyons ha praticamente coperto la base.
Prendendo in prestito dall'esempio precedente (rimuovendo le righe dopo lo schema) Volevo solo aggiungere:

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

}); 

Per caricare dal app/controllers/items.js

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

Un altro modo senza il 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 

Negli app/controllers/items.js

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

E da dove verranno chiamati i controller? – Warz

+0

Non sono sicuro di aver capito la tua domanda. Puoi chiarire? – user1460015

35

Un paio di risposte qui davvero mi ha aiutato a sviluppare un approccio alternativo. La domanda iniziale riguarda lo spezzare solo definizione Schema, ma preferisco raggruppare le definizioni Schema e Modello nello stesso file.

Questo è soprattutto l'idea di Peter, solo esportare la definizione del modello sovrascrivendo module.exports per rendere l'accesso al modello del vostro controller un po 'meno verbose:

layout del progetto:

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

modelli/Articolo .js sarà simile:

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 

E si accedere al modello in un controllore, dicono user.js, come:

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

... 

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

Non dimenticare di chiamare mongoose.connect (..) in server.js o in qualsiasi altro posto che ritieni appropriato!

9

Recentemente ho risposto a una domanda di Quora per quanto riguarda questo stesso problema. http://qr.ae/RoCld1

Quello che ho trovato molto bello e consente di risparmiare sulla quantità di richiedono chiamate è quello di strutturare i vostri modelli in una singola directory. Assicurati di avere un solo modello per file.

Creare un file index.js nella stessa directory dei modelli. Aggiungi questo codice ad esso. Assicurati di aggiungere le necessarie fs richiedono

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

Ora è possibile chiamare tutti i vostri modelli come segue:

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

Questa è di gran lunga la migliore risposta, l'automazione risparmia molta ridondanza nel codice e finisce per sembrare molto pulita. – zoubida13

+0

Suppongo che tu abbia il tuo codice di inizializzazione db nella radice del progetto. Qualche idea su come si comporta? Grazie –

Problemi correlati