sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo usar eventos para mantener la lógica mongodb fuera de los controladores de solicitudes de node.js

Aquí está la solución que he encontrado.

Usé mongojs lo que simplifica enormemente la interfaz mongodb, a costa de la flexibilidad en la configuración, pero oculta las devoluciones de llamada anidadas que requiere el controlador mongodb. También hace que la sintaxis se parezca mucho más al cliente mongo.

Luego envuelvo el objeto de respuesta HTTP en un cierre y paso este cierre al método de consulta mongodb en una devolución de llamada.

var MongoProvider = require('./MongoProvider');
MongoProvider.setCollection('things');

exports.index = function(request, response){
    function sendResponse(err, data) {
        if (err) { 
            response.send(500, err);
        }    
        response.send(data);
    };

    MongoProvider.fetchAll(things, sendResponse);
};

Todavía consiste esencialmente en pasar el objeto de respuesta al proveedor de la base de datos, pero al envolverlo en un cierre que sabe cómo manejar la respuesta, mantiene esa lógica fuera de mi módulo de base de datos.

Una ligera mejora es usar una función para crear un cierre de controlador de respuesta fuera de mi controlador de solicitud:

function makeSendResponse(response){
    return function sendResponse(err, data) {
        if (err) {
            console.warn(err);
            response.send(500, {error: err});
            return;
        }

        response.send(data);
    };
}

Así que ahora mi controlador de solicitudes se ve así:

exports.index = function(request, response) {
    response.send(makeSendResponse(response));
}

Y mi MongoProvider se ve así:

var mongojs = require('mongojs');

MongoProvider = function(config) {
this.configure(config);
    this.db = mongojs.connect(this.url, this.collections);
}

MongoProvider.prototype.configure = function(config) {
    this.url = config.host + "/" + config.name;
    this.collections = config.collections;
}

MongoProvider.prototype.connect = function(url, collections) {
    return mongojs.connect(this.url, this.collections);
}

MongoProvider.prototype.fetchAll = function fetchAll(collection, callback) {
    this.db(collection).find(callback);
}

MongoProvider.prototype.fetchById = function fetchById(id, collection, callback) {
    var objectId = collection.db.bson_serializer.ObjectID.createFromHexString(id.toString());

    this.db(collection).findOne({ "_id": objectId }, callback);
}

MongoProvider.prototype.fetchMatches = function fetchMatches(json, collection, callback) {
    this.db(collection).find(Json.parse(json), callback);
}

module.exports = MongoProvider;

También puedo extender MongoProvider para colecciones específicas para simplificar la API y realizar una validación adicional:

ThingsProvider = function(config) {
    this.collection = 'things';
    this.mongoProvider = new MongoProvider(config);
    things = mongoProvider.db.collection('things');
}

ThingsProvider.prototype.fetchAll = function(callback) {
    things.fetchAll(callback);
}

//etc...

module.exports = ThingsProvider;