{"id":2918,"date":"2017-03-07T11:11:30","date_gmt":"2017-03-07T19:11:30","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2918"},"modified":"2025-06-13T17:33:05","modified_gmt":"2025-06-14T00:33:05","slug":"migrate-mongodb-couchbase-n1ql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/migrate-mongodb-couchbase-n1ql\/","title":{"rendered":"Migrar de MongoDB a Couchbase con N1QL"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">Los clientes a menudo nos dicen que se est\u00e1n preparando para migrar de MongoDB a Couchbase. Vienen, en parte, porque est\u00e1n cansados de los problemas que han experimentado aprendiendo a consultar MongoDB. Couchbase con N1QL proporciona una alternativa mejor, especialmente para escalar aplicaciones modernas.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Por desgracia, con MongoDB, las opciones de migraci\u00f3n pueden ser limitadas. Una sobre la que escrib\u00ed recientemente implica mover<\/span> de <a href=\"https:\/\/www.couchbase.com\/blog\/es\/migrating-mongodb-mongoose-restful-api-couchbase-ottoman\/\" target=\"_blank\" rel=\"noopener noreferrer\">De MongoDB con Mongoose a Couchbase con Ottoman<\/a>.  El n\u00facleo de ese tutorial giraba en torno al uso de dos herramientas ODM diferentes en Node.js que compart\u00edan las mismas APIs, haciendo que la transici\u00f3n fuera casi perfecta.  Sin embargo, \u00bfqu\u00e9 pasa si no est\u00e1s usando un ODM en MongoDB y no tienes inter\u00e9s en usar uno?<\/p>\n<p>En esta ocasi\u00f3n vamos a echar un vistazo a c\u00f3mo mover una aplicaci\u00f3n Node.js que utiliza MongoDB y el lenguaje de consultas de MongoDB a Couchbase con N1QL.  En resumen, N1QL es una tecnolog\u00eda que te permite ejecutar consultas SQL contra datos JSON complejos.  Esto hace que no s\u00f3lo sea f\u00e1cil de usar, sino tambi\u00e9n muy limpio en la capa de aplicaci\u00f3n.  M\u00e1s informaci\u00f3n sobre N1QL se puede encontrar en el <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/4.6\/getting-started\/try-a-query.html\" target=\"_blank\" rel=\"noopener noreferrer\">Portal para desarrolladores de Couchbase<\/a>.<\/p>\n<p><!--more--><\/p>\n<p>Vamos a utilizar el mismo problema de ejemplo utilizado en la secci\u00f3n <a href=\"https:\/\/www.couchbase.com\/blog\/es\/migrating-mongodb-mongoose-restful-api-couchbase-ottoman\/\" target=\"_blank\" rel=\"noopener noreferrer\">art\u00edculo anterior<\/a>pero no pasa nada si no lo has visto.  Todo aqu\u00ed se iniciar\u00e1 con una pizarra limpia.<\/p>\n<h2>Requisitos<\/h2>\n<p>Hay algunos requisitos que deben cumplirse para asegurarse de que tiene \u00e9xito con esta gu\u00eda.  Se pueden ver de la siguiente manera:<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li><a href=\"https:\/\/www.mongodb.com\/download-center\" target=\"_blank\" rel=\"noopener noreferrer\">MongoDB<\/a> 3.4+<\/li>\n<li><a href=\"https:\/\/www.couchbase.com\/blog\/es\/downloads\/\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase<\/a> 4.5+<\/li>\n<li><a href=\"https:\/\/nodejs.org\/en\/\" target=\"_blank\" rel=\"noopener noreferrer\">Node.js<\/a> 6.0+<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Dado que vamos a ver tanto el equivalente de MongoDB como el de Couchbase, deber\u00edas tener ambas bases de datos a tu disposici\u00f3n.  Si ya eres desarrollador de MongoDB, puede que muchas cosas te resulten familiares, pero eso es decisi\u00f3n tuya.<\/p>\n<h2>Comprender el modelo de datos NoSQL<\/h2>\n<p>Antes de desarrollar la API RESTful con cualquiera de las dos tecnolog\u00edas, conviene entender primero el modelo de datos que se va a utilizar.<\/p>\n<p>Aunque tanto MongoDB como Couchbase son bases de datos documentales, no son totalmente iguales.  MongoDB almacena los datos como BSON mientras que Couchbase lo hace como JSON.  Desde una perspectiva de modelado, realmente no nos importar\u00e1.<\/p>\n<p>Tomemos el modelo de datos de una escuela en la que hay alumnos y cursos.  Para cada curso ofrecido en la escuela, usted podr\u00eda tener un documento que se parece a lo siguiente:<\/p>\n<pre class=\"lang:default highlight:0 decode:true\" title=\"Modelo NoSQL para cursos\">{\r\n    \"id\": \"course-1\",\r\n    \"type\": \"course\",\r\n    \"name\": \"Computer Science 101\",\r\n    \"term\": \"F2017\",\r\n    \"students\": [\r\n        \"student-1\",\r\n        \"student-2\"\r\n    ]\r\n}<\/pre>\n<p>Cada curso mantendr\u00e1 una lista de todos los alumnos que se hayan matriculado.  En este caso, la lista consistir\u00e1 en valores id que hacen referencia a otros documentos.  Estamos estableciendo nuestras propias relaciones entre documentos.<\/p>\n<p>Para cada estudiante de la escuela, pueden tener un documento NoSQL que se parece a lo siguiente:<\/p>\n<pre class=\"lang:default highlight:0 decode:true\" title=\"Modelo NoSQL para estudiantes\">{\r\n    \"id\": \"student-1\",\r\n    \"type\": \"student\",\r\n    \"firstname\": \"Nic\",\r\n    \"lastname\": \"Raboy\",\r\n    \"courses\": [\r\n        \"course-1\",\r\n        \"course-25\"\r\n    ]\r\n}<\/pre>\n<p>Observe que el documento anterior es similar a c\u00f3mo modelamos nuestros cursos.  Cada estudiante mantendr\u00e1 una lista de todos los cursos en los que est\u00e1 inscrito.  Estos cursos son ids que hacen referencia al documento del curso apropiado.<\/p>\n<p>Hay cientos de formas diferentes de modelar nuestros documentos, \u00e9ste es s\u00f3lo un ejemplo.  Para obtener m\u00e1s informaci\u00f3n sobre el modelado de datos, echa un vistazo a este <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/data-modeling\/intro-data-modeling.html\" target=\"_blank\" rel=\"noopener noreferrer\">documentaci\u00f3n<\/a>.<\/p>\n<p>Ahora que tenemos un modelo para nuestros documentos, podemos centrarnos en construir una API con cada tecnolog\u00eda.<\/p>\n<h2>Desarrollo de una API con el lenguaje de consulta de MongoDB<\/h2>\n<p>Aunque puede que tengas tu propio c\u00f3digo de aplicaci\u00f3n MongoDB, vamos a crear uno desde cero para que la migraci\u00f3n sea muy f\u00e1cil de entender.<\/p>\n<p>Empecemos por crear un nuevo proyecto desde nuestro S\u00edmbolo del sistema o Terminal:<\/p>\n<pre class=\"lang:sh decode:true\">npm init --y\r\nnpm install express body-parser mongodb --save<\/pre>\n<p>Los comandos anteriores crear\u00e1n un nuevo\u00a0<strong>paquete.json<\/strong> en su directorio de trabajo actual e instale las dependencias necesarias del framework y la base de datos.<\/p>\n<p>Al final del d\u00eda, queremos que nuestro proyecto MongoDB tenga la siguiente estructura:<\/p>\n<pre class=\"lang:default highlight:0 decode:true\">app.js\r\nroutes\/\r\n    courses.js\r\n    students.js\r\nmodels\/\r\n    student.js\r\n    course.js\r\npackage.json\r\nnode_modules\/<\/pre>\n<p>Toda la interacci\u00f3n con la base de datos se realizar\u00e1 desde cada uno de los <strong>modelos<\/strong> y todo el enrutamiento de la API y la interacci\u00f3n con el cliente se har\u00e1 desde el\u00a0<strong>rutas<\/strong> archivos.  El arranque de la aplicaci\u00f3n y la conexi\u00f3n a la base de datos se realizar\u00e1 desde el archivo\u00a0<strong>app.js<\/strong> archivo.<\/p>\n<h3>Creaci\u00f3n de un modelo de base de datos MongoDB dentro de la aplicaci\u00f3n<\/h3>\n<p>Echemos un vistazo a uno de nuestros modelos de base de datos.  Abra el proyecto\u00a0<strong>modelos\/curso.js<\/strong> e incluya el siguiente c\u00f3digo:<\/p>\n<pre class=\"lang:js decode:true\">var Database = require(\"..\/..\/app\").database;\r\nvar ObjectId = require(\"mongodb\").ObjectId;\r\n\r\nfunction CourseModel() { };\r\n\r\nCourseModel.save = function(data, callback) {\r\n    Database.collection(\"courses\").insertOne(data, function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n}\r\n\r\nCourseModel.updateStudents = function(id, students, callback) {\r\n    Database.collection(\"courses\").updateOne({ \"_id\": new ObjectId(id) },\r\n        {\r\n            $set: { \"students\": students }\r\n        }, function(error, result) {\r\n            if(error) {\r\n                return callback(error, null);\r\n            }\r\n            callback(null, result);\r\n        }\r\n    );\r\n}\r\n\r\nCourseModel.getById = function(documentId, callback) {\r\n    var cursor = Database.collection(\"courses\").aggregate([\r\n        { \"$match\": { \"_id\": new ObjectId(documentId) } },\r\n        { \"$unwind\": { \"path\": \"$students\", \"preserveNullAndEmptyArrays\": true } },\r\n        {\r\n            \"$lookup\": {\r\n                \"from\": \"students\",\r\n                \"localField\": \"students\",\r\n                \"foreignField\": \"_id\",\r\n                \"as\": \"studentObjects\"\r\n            }\r\n        },\r\n        { \"$unwind\": { \"path\": \"$studentObjects\", \"preserveNullAndEmptyArrays\": true} },\r\n        { \"$group\": {\r\n            \"_id\": {\r\n                \"_id\": \"$_id\",\r\n                \"name\": \"$name\"\r\n            },\r\n            \"students\": { \"$push\": \"$studentObjects\" }\r\n        }},\r\n        {\r\n            \"$project\": {\r\n                \"_id\": \"$_id._id\",\r\n                \"name\": \"$_id.name\",\r\n                \"students\": \"$students\"\r\n            }\r\n        },\r\n        { \"$limit\": 1 }\r\n    ]);\r\n    cursor.toArray(callback);\r\n};\r\n\r\nCourseModel.getAll = function(callback) {\r\n    var cursor = Database.collection(\"courses\").aggregate([\r\n        { \"$unwind\": { \"path\": \"$students\", \"preserveNullAndEmptyArrays\": true} },\r\n        {\r\n            \"$lookup\": {\r\n                \"from\": \"students\",\r\n                \"localField\": \"students\",\r\n                \"foreignField\": \"_id\",\r\n                \"as\": \"studentObjects\"\r\n            }\r\n        },\r\n        { \"$unwind\": { \"path\": \"$studentObjects\", \"preserveNullAndEmptyArrays\": true} },\r\n        { \"$group\": {\r\n            \"_id\": {\r\n                \"_id\": \"$_id\",\r\n                \"name\": \"$name\"\r\n            },\r\n            \"students\": { \"$push\": \"$studentObjects\" }\r\n        }},\r\n        {\r\n            \"$project\": {\r\n                \"_id\": \"$_id._id\",\r\n                \"name\": \"$_id.name\",\r\n                \"students\": \"$students\"\r\n            }\r\n        }\r\n    ]);\r\n    cursor.toArray(callback);\r\n};\r\n\r\nmodule.exports = CourseModel;<\/pre>\n<p>En el modelo de base de datos anterior ocurren muchas cosas.  Tenemos que desglosarlo para que sea f\u00e1cil de entender.  Cuanto m\u00e1s entendamos, m\u00e1s f\u00e1cil ser\u00e1 el proceso de migraci\u00f3n a Couchbase.<\/p>\n<p>Cuando deseamos guardar un documento, tenemos la opci\u00f3n\u00a0<code>guardar<\/code> m\u00e9todo:<\/p>\n<pre class=\"lang:js decode:true\">CourseModel.save = function(data, callback) {\r\n    Database.collection(\"courses\").insertOne(data, function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n}<\/pre>\n<p>Utilizando la base de datos abierta podemos insertar un \u00fanico documento en la colecci\u00f3n deseada utilizando la funci\u00f3n\u00a0<code>insertarUno<\/code> funci\u00f3n.  En esta funci\u00f3n pasamos\u00a0<code>datos<\/code> que puede ser un objeto JavaScript de cualquier complejidad que deseemos guardar.  Una vez guardado, el resultado ser\u00e1 devuelto al m\u00e9todo padre que lo llam\u00f3.<\/p>\n<p>\u00bfY si queremos actualizar un documento que ya existe?  En concreto, \u00bfqu\u00e9 ocurre si queremos a\u00f1adir un alumno a un curso ya existente?<\/p>\n<p>En este ejemplo concreto, podemos actualizar todo el archivo\u00a0<code>estudiantes<\/code> que existe en el documento:<\/p>\n<pre class=\"lang:js decode:true\">CourseModel.updateStudents = function(id, students, callback) {\r\n    Database.collection(\"courses\").updateOne({ \"_id\": new ObjectId(id) },\r\n        {\r\n            $set: { \"students\": students }\r\n        }, function(error, result) {\r\n            if(error) {\r\n                return callback(error, null);\r\n            }\r\n            callback(null, result);\r\n        }\r\n    );\r\n}<\/pre>\n<p>El c\u00f3digo anterior utilizar\u00e1 el\u00a0<code>updateUno<\/code> para buscar un documento concreto por su id y sustituir el m\u00e9todo\u00a0<code>estudiantes<\/code> con una nueva que proporcionamos mediante la funci\u00f3n\u00a0<code>actualizarEstudiantes<\/code> funci\u00f3n.<\/p>\n<p>Nada demasiado dif\u00edcil hasta ahora y ning\u00fan estr\u00e9s real a\u00f1adido al desarrollador.<\/p>\n<p>Aqu\u00ed es donde las cosas cambian.  Cuando guardamos datos estamos guardando un array de valores id.  No son datos que queramos ver en operaciones de consulta.  En su lugar, queremos rellenar o expandir estos valores de id en sus equivalentes de documento:<\/p>\n<pre class=\"lang:js decode:true\">CourseModel.getAll = function(callback) {\r\n    var cursor = Database.collection(\"courses\").aggregate([\r\n        { \"$unwind\": { \"path\": \"$students\", \"preserveNullAndEmptyArrays\": true} },\r\n        {\r\n            \"$lookup\": {\r\n                \"from\": \"students\",\r\n                \"localField\": \"students\",\r\n                \"foreignField\": \"_id\",\r\n                \"as\": \"studentObjects\"\r\n            }\r\n        },\r\n        { \"$unwind\": { \"path\": \"$studentObjects\", \"preserveNullAndEmptyArrays\": true} },\r\n        { \"$group\": {\r\n            \"_id\": {\r\n                \"_id\": \"$_id\",\r\n                \"name\": \"$name\"\r\n            },\r\n            \"students\": { \"$push\": \"$studentObjects\" }\r\n        }},\r\n        {\r\n            \"$project\": {\r\n                \"_id\": \"$_id._id\",\r\n                \"name\": \"$_id.name\",\r\n                \"students\": \"$students\"\r\n            }\r\n        }\r\n    ]);\r\n    cursor.toArray(callback);\r\n};<\/pre>\n<p>Para que esto sea posible, primero hay que aplanar la matriz mediante una funci\u00f3n\u00a0<code>$unwind<\/code> y unidos a trav\u00e9s de un\u00a0<code>1TP4B\u00fasqueda<\/code> operaci\u00f3n.  La cosa no acaba ah\u00ed, porque queremos que nuestros resultados tengan el mismo formato, sustituyendo \u00fanicamente los identificadores de los objetos.  Debido a esto tenemos que hacer m\u00e1s aplanamiento, agrupaci\u00f3n y manipulaciones.<\/p>\n<p>Una explicaci\u00f3n completa de la uni\u00f3n de datos en MongoDB frente a la uni\u00f3n de datos en Couchbase se puede ver en un <a href=\"https:\/\/www.couchbase.com\/blog\/es\/joining-nosql-documents-mongodb-query-language-vs-couchbase-n1ql\/\" target=\"_blank\" rel=\"noopener noreferrer\">minucioso art\u00edculo que escrib\u00ed anteriormente<\/a> sobre el tema.<\/p>\n<p>En resumen, cuanto m\u00e1s complicados sean los datos, m\u00e1s complicada ser\u00e1 la consulta de agregaci\u00f3n.  Para un modelo de datos flexible, esto se convierte en poco flexible para un desarrollador de aplicaciones.<\/p>\n<p>Echemos un vistazo r\u00e1pido a nuestro otro modelo, el que gestionar\u00e1 los datos de los alumnos.  Abra el proyecto\u00a0<strong>modelos\/estudiante.js<\/strong> e incluya el siguiente c\u00f3digo JavaScript:<\/p>\n<pre class=\"lang:js decode:true\">var Database = require(\"..\/..\/app\").database;\r\nvar ObjectId = require(\"mongodb\").ObjectId;\r\n\r\nfunction StudentModel() { };\r\n\r\nStudentModel.save = function(data, callback) {\r\n    Database.collection(\"students\").insertOne(data, function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n}\r\n\r\nStudentModel.updateCourses = function(id, courses, callback) {\r\n    Database.collection(\"students\").updateOne({ \"_id\": new ObjectId(id) },\r\n        {\r\n            $set: { \"courses\": courses }\r\n        }, function(error, result) {\r\n            if(error) {\r\n                return callback(error, null);\r\n            }\r\n            callback(null, result);\r\n        }\r\n    );\r\n}\r\n\r\nStudentModel.getById = function(documentId, callback) {\r\n    var cursor = Database.collection(\"students\").aggregate([\r\n        { \"$match\": { \"_id\": new ObjectId(documentId) } },\r\n        { \"$unwind\": { \"path\": \"$courses\", \"preserveNullAndEmptyArrays\": true } },\r\n        {\r\n            \"$lookup\": {\r\n                \"from\": \"courses\",\r\n                \"localField\": \"courses\",\r\n                \"foreignField\": \"_id\",\r\n                \"as\": \"courseObjects\"\r\n            }\r\n        },\r\n        { \"$unwind\": { \"path\": \"$courseObjects\", \"preserveNullAndEmptyArrays\": true } },\r\n        { \"$group\": {\r\n            \"_id\": {\r\n                \"_id\": \"$_id\",\r\n                \"name\": \"$name\"\r\n            },\r\n            \"courses\": { \"$push\": \"$courseObjects\" }\r\n        }},\r\n        {\r\n            \"$project\": {\r\n                \"_id\": \"$_id._id\",\r\n                \"name\": \"$_id.name\",\r\n                \"courses\": \"$courses\"\r\n            }\r\n        },\r\n        { \"$limit\": 1 }\r\n    ]);\r\n    cursor.toArray(callback);\r\n};\r\n\r\nStudentModel.getAll = function(callback) {\r\n    var cursor = Database.collection(\"students\").aggregate([\r\n        { \"$unwind\": { \"path\": \"$courses\", \"preserveNullAndEmptyArrays\": true } },\r\n        {\r\n            \"$lookup\": {\r\n                \"from\": \"courses\",\r\n                \"localField\": \"courses\",\r\n                \"foreignField\": \"_id\",\r\n                \"as\": \"courseObjects\"\r\n            }\r\n        },\r\n        { \"$unwind\": { \"path\": \"$courseObjects\", \"preserveNullAndEmptyArrays\": true } },\r\n        { \"$group\": {\r\n            \"_id\": {\r\n                \"_id\": \"$_id\",\r\n                \"firstname\": \"$firstname\",\r\n                \"lastname\": \"$lastname\",\r\n                \"address\": \"$address\"\r\n            },\r\n            \"courses\": { \"$push\": \"$courseObjects\" }\r\n        }},\r\n        {\r\n            \"$project\": {\r\n                \"_id\": \"$_id._id\",\r\n                \"firstname\": \"$_id.firstname\",\r\n                \"lastname\": \"$_id.lastname\",\r\n                \"address\": \"$_id.address\",\r\n                \"courses\": \"$courses\"\r\n            }\r\n        }\r\n    ]);\r\n    cursor.toArray(callback);\r\n};\r\n\r\nmodule.exports = StudentModel;<\/pre>\n<p>Pr\u00e1cticamente las mismas reglas se aplican al modelo anterior frente al modelo que vimos representando los datos del curso.  Esto se debe a que los dos modelos de documentos eran muy similares para empezar.  Plano en su mayor parte con un array de valores id.<\/p>\n<p>Esto nos lleva a los puntos finales de la API que hacen uso de estos m\u00e9todos de base de datos.<\/p>\n<h3>Creaci\u00f3n de las rutas API RESTful para la aplicaci\u00f3n<\/h3>\n<p>Esta es la parte f\u00e1cil, y en realidad la m\u00e1s coherente entre las dos tecnolog\u00edas de bases de datos porque no depende de la base de datos.<\/p>\n<p>Echemos un vistazo al proyecto de\u00a0<strong>rutas\/cursos.js<\/strong> file:<\/p>\n<pre class=\"lang:js decode:true\">var CourseModel = require(\"..\/models\/course\");\r\n\r\nvar router = function(app) {\r\n\r\n    app.get(\"\/courses\", function(request, response) {\r\n        CourseModel.getAll(function(error, result) {\r\n            if(error) {\r\n                return response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            response.send(result);\r\n        });\r\n    });\r\n\r\n    app.get(\"\/course\/:id\", function(request, response) {\r\n        CourseModel.getById(request.params.id, function(error, result) {\r\n            if(error) {\r\n                return response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            response.send(result[0]);\r\n        });\r\n    });\r\n\r\n    app.post(\"\/courses\", function(request, response) {\r\n        if(!request.body.name) {\r\n            return response.status(401).send({ \"success\": false, \"message\": \"A `name` is required\"});\r\n        }\r\n        CourseModel.save(request.body, function(error, course) {\r\n            if(error) {\r\n                return response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            response.send(course);\r\n        });\r\n    });\r\n\r\n}\r\n\r\nmodule.exports = router;<\/pre>\n<p>En el c\u00f3digo anterior tenemos tres rutas API.  Desde un cliente externo podremos listar todos los cursos, encontrar un curso en particular o guardar un nuevo curso.<\/p>\n<p>Dependiendo del punto final que se alcance, se ejecutar\u00e1 la funci\u00f3n apropiada del modelo de base de datos.  No se hace mucho trabajo pesado en las rutas, que bas\u00e1ndose en su nombre, s\u00f3lo sirven para enrutar.<\/p>\n<p>El otro archivo de enrutamiento va a ser un poco diferente.  Abra el archivo\u00a0<strong>rutas\/estudiantes.js<\/strong> e incluya el siguiente c\u00f3digo JavaScript:<\/p>\n<pre class=\"lang:js decode:true\">var StudentModel = require(\"..\/models\/student\");\r\nvar CourseModel = require(\"..\/models\/course\");\r\n\r\nvar router = function(app) {\r\n\r\n    app.get(\"\/students\", function(request, response) {\r\n        StudentModel.getAll(function(error, result) {\r\n            if(error) {\r\n                response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            response.send(result);\r\n        });\r\n    });\r\n\r\n    app.get(\"\/student\/:id\", function(request, response) {\r\n        StudentModel.getById(request.params.id, function(error, result) {\r\n            if(error) {\r\n                response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            response.send(result);\r\n        });\r\n    });\r\n\r\n    app.post(\"\/students\", function(request, response) {\r\n        if(!request.body.firstname) {\r\n            return response.status(401).send({ \"success\": false, \"message\": \"A `firstname` is required\"});\r\n        } else if(!request.body.lastname) {\r\n            return response.status(401).send({ \"success\": false, \"message\": \"A `lastname` is required\"});\r\n        } else if(!request.body.address) {\r\n            return response.status(401).send({ \"success\": false, \"message\": \"An `address` is required\"});\r\n        }\r\n        StudentModel.save(request.body, function(error, student) {\r\n            if(error) {\r\n                return response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            response.send(student);\r\n        });\r\n    });\r\n\r\n    app.post(\"\/student\/course\", function(request, response) {\r\n        if(!request.body.student_id) {\r\n            return response.status(401).send({ \"success\": false, \"message\": \"A `student_id` is required\" });\r\n        } else if(!request.body.course_id) {\r\n            return response.status(401).send({ \"success\": false, \"message\": \"A `course_id` is required\" });\r\n        }\r\n        CourseModel.getById(request.body.course_id, function(error, course) {\r\n            if(error) {\r\n                return response.status(401).send({ \"success\": false, \"message\": error});\r\n            }\r\n            StudentModel.getById(request.body.student_id, function(error, student) {\r\n                if(error) {\r\n                    return response.status(401).send({ \"success\": false, \"message\": error});\r\n                }\r\n                if(course != null &amp;&amp; student != null) {\r\n                    if(!student[0].courses) {\r\n                        student[0].courses = [];\r\n                    }\r\n                    if(!course[0].students) {\r\n                        course[0].students = [];\r\n                    }\r\n                    var courses = [];\r\n                    var students = [];\r\n                    for(var i = 0; i &lt; student[0].courses.length; i++) {\r\n                        courses.push(student[0].courses[i]._id);\r\n                    }\r\n                    for(var i = 0; i &lt; course[0].students.length; i++) {\r\n                        students.push(course[0].students[i]._id);\r\n                    }\r\n                    courses.push(course[0]._id);\r\n                    students.push(student[0]._id);\r\n                    StudentModel.updateCourses(student[0]._id, courses, function(error, result) {});\r\n                    CourseModel.updateStudents(course[0]._id, students, function(error, result) {});\r\n                    response.send(student[0]);\r\n                } else {\r\n                    return response.status(401).send({ \"success\": false, \"message\": \"The `student_id` or `course_id` was invalid\"});\r\n                }\r\n            });\r\n        });\r\n    });\r\n\r\n}\r\n\r\nmodule.exports = router;<\/pre>\n<p>Al igual que en la otra ruta, ocurren muchas cosas, pero la mayor\u00eda son casi id\u00e9nticas.  Donde hay diferencias es en el\u00a0<code>\/estudiante\/curso<\/code> responsable de a\u00f1adir cursos a un estudiante y estudiantes a un curso.<\/p>\n<p>Cuando se accede a este punto final, primero obtenemos la informaci\u00f3n del estudiante y del curso bas\u00e1ndonos en el valor de id pasado.  Ambos deben existir, de lo contrario se producir\u00e1 un error.  Si ambos existen, introduciremos el id del estudiante en el campo\u00a0<code>estudiantes<\/code> para el documento del curso y el id del curso en el array\u00a0<code>cursos<\/code> del documento del alumno.  Luego llamaremos a nuestro m\u00e9todo de actualizaci\u00f3n y devolveremos un resultado al usuario final.<\/p>\n<h3>Reunir todo y poner en marcha la aplicaci\u00f3n<\/h3>\n<p>La API est\u00e1 lista en este punto.  S\u00f3lo tenemos que arrancar la aplicaci\u00f3n Node.js y conectarnos a la base de datos.  Esta es la parte f\u00e1cil.<\/p>\n<p>Abra el archivo\u00a0<strong>app.js<\/strong> e incluya el siguiente c\u00f3digo:<\/p>\n<pre class=\"lang:js decode:true\">var MongoClient = require(\"mongodb\").MongoClient;\r\nvar Express = require(\"express\");\r\nvar BodyParser = require(\"body-parser\");\r\n\r\nvar app = Express();\r\napp.use(BodyParser.json());\r\n\r\nMongoClient.connect(\"mongodb:\/\/localhost:27017\/example\", function(error, database) {\r\n    if(error) {\r\n        return console.log(\"Could not establish a connection to MongoDB\");\r\n    }\r\n    module.exports.database = database;\r\n    var studentRoutes = require(\".\/mongodb\/routes\/students\")(app);\r\n    var courseRoutes = require(\".\/mongodb\/routes\/courses\")(app);\r\n    var server = app.listen(3000, function() {\r\n        console.log(\"Connected on port 3000...\");\r\n    });\r\n});<\/pre>\n<p>En el c\u00f3digo anterior estamos importando cada una de las dependencias que hemos descargado e inicializando Express Framework.  Antes de empezar a servir la API, necesitamos establecer una conexi\u00f3n con MongoDB.  Una vez establecida la conexi\u00f3n, las rutas se conectan y la aplicaci\u00f3n comienza a servir.<\/p>\n<p>En este punto se puede acceder a la API RESTful en https:\/\/localhost:3000 y probarla con herramientas populares como <a href=\"https:\/\/www.thepolyglotdeveloper.com\/2015\/01\/using-postman-troubleshoot-restful-api-requests\/\" target=\"_blank\" rel=\"noopener noreferrer\">Cartero<\/a> o Fiddler.<\/p>\n<h2>Desarrollo de una API con Couchbase y N1QL<\/h2>\n<p>As\u00ed que tenemos un ejemplo con el que trabajar cuando se trata de MongoDB y Node.js.  Ese ejemplo utiliza el lenguaje de consulta MongoDB cuando se comunica con la base de datos.<\/p>\n<p>Ahora vamos a tomar esa aplicaci\u00f3n y moverla a <a href=\"https:\/\/www.couchbase.com\/blog\/es\/\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase<\/a>.  Hacemos esto porque Couchbase no s\u00f3lo escala mejor y tiene mejor rendimiento, el lenguaje de consulta es mucho m\u00e1s simple y f\u00e1cil de mantener dentro de una aplicaci\u00f3n.<\/p>\n<p>Al igual que con la aplicaci\u00f3n MongoDB, vamos a empezar desde cero, aunque gran parte de lo que veamos ser\u00e1 id\u00e9ntico.  Desde el S\u00edmbolo del sistema o Terminal, ejecuta lo siguiente:<\/p>\n<pre class=\"lang:sh highlight:0 decode:true\">npm init --y\r\nnpm install express body-parser couchbase --save<\/pre>\n<p>Los comandos anteriores deber\u00edan resultarte familiares.  Estamos creando un\u00a0<strong>paquete.json<\/strong> e instalando nuestras dependencias, pero en lugar de MongoDB estamos usando Couchbase.<\/p>\n<p>El proyecto tendr\u00e1 la misma estructura que el proyecto anterior.  Deber\u00eda tener este aspecto:<\/p>\n<pre class=\"lang:default highlight:0 decode:true\">app.js\r\nroutes\/\r\n    courses.js\r\n    students.js\r\nmodels\/\r\n    course.js\r\n    student.js\r\npackage.json\r\nnode_modules\/<\/pre>\n<p>La misma l\u00f3gica vista anteriormente terminar\u00e1 en cada uno de estos archivos.  La diferencia es la sintaxis para Couchbase.<\/p>\n<h3>Creaci\u00f3n de un modelo de base de datos Couchbase dentro de la aplicaci\u00f3n<\/h3>\n<p>Empezando con el mismo orden, vamos a crear las funciones de nuestro modelo de base de datos.  Como se mencion\u00f3 anteriormente, vamos a utilizar N1QL que es un extremo destacado de Couchbase porque te permite escribir consultas SQL.  Estas consultas se ejecutan en la base de datos y no dentro de tu aplicaci\u00f3n Node.js.<\/p>\n<p>Abra el archivo\u00a0<strong>modelos\/curso.js<\/strong> e incluya el siguiente c\u00f3digo:<\/p>\n<pre class=\"lang:js decode:true\">var Uuid = require(\"uuid\");\r\nvar Bucket = require(\"..\/..\/app\").bucket;\r\nvar N1qlQuery = require(\"couchbase\").N1qlQuery;\r\n\r\nfunction CourseModel() { };\r\n\r\nCourseModel.save = function(data, callback) {\r\n    data.id = Uuid.v4();\r\n    data.type = \"course\";\r\n    data.students = [];\r\n    var statement = \"INSERT INTO `\" + Bucket._name + \"` (KEY, VALUE) VALUES ($1, $2) RETURNING `\" + Bucket._name + \"`.*\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    Bucket.query(query, [data.id, data], function(error, result) {\r\n        if(error) {\r\n            callback(error, null);\r\n            return;\r\n        }\r\n        callback(null, result);\r\n    });\r\n}\r\n\r\nCourseModel.updateStudents = function(id, courses, callback) {\r\n    var statement = \"UPDATE `\" + Bucket._name + \"` USE KEYS $1 SET students = $2 RETURNING `\" + Bucket._name + \"`.*\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    Bucket.query(query, [id, courses], function(error, result) {\r\n        if(error) {\r\n            callback(error, null);\r\n            return;\r\n        }\r\n        callback(null, result);\r\n    });\r\n}\r\n\r\nCourseModel.getById = function(documentId, callback) {\r\n    var statement = \"SELECT s.id, s.type, s.name, \" +\r\n                    \"(SELECT t.* FROM `\" + Bucket._name + \"` AS t USE KEYS s.students) AS students \" +\r\n                    \"FROM `\" + Bucket._name + \"` AS s \" +\r\n                    \"WHERE s.type = 'course' AND s.id = $1\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    Bucket.query(query, [documentId], function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n};\r\n\r\nCourseModel.getAll = function(callback) {\r\n    var statement = \"SELECT s.id, s.type, s.name, \" +\r\n                    \"(SELECT t.* FROM `\" + Bucket._name + \"` AS t USE KEYS s.students) AS students \" +\r\n                    \"FROM `\" + Bucket._name + \"` AS s \" +\r\n                    \"WHERE s.type = 'course'\";\r\n    var query = N1qlQuery.fromString(statement).consistency(N1qlQuery.Consistency.REQUEST_PLUS);\r\n    Bucket.query(query, function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n};\r\n\r\nmodule.exports = CourseModel;<\/pre>\n<p>En el c\u00f3digo anterior tenemos el mismo conjunto de funciones relacionadas con la base de datos que vimos en el ejemplo de MongoDB.  Dentro de cada una de estas funciones hay consultas N1QL.  No solo consultas N1QL, sino consultas N1QL parametrizadas para ayudar a combatir los ataques de inyecci\u00f3n SQL.<\/p>\n<p>Eche un vistazo al\u00a0<code>getAll<\/code> que antes era supercomplicado en la versi\u00f3n de MongoDB:<\/p>\n<pre class=\"lang:js decode:true\">CourseModel.getAll = function(callback) {\r\n    var statement = \"SELECT s.id, s.type, s.name, \" +\r\n                    \"(SELECT t.* FROM `\" + Bucket._name + \"` AS t USE KEYS s.students) AS students \" +\r\n                    \"FROM `\" + Bucket._name + \"` AS s \" +\r\n                    \"WHERE s.type = 'course'\";\r\n    var query = N1qlQuery.fromString(statement).consistency(N1qlQuery.Consistency.REQUEST_PLUS);\r\n    Bucket.query(query, function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n};<\/pre>\n<p>En esta ocasi\u00f3n tenemos una consulta sencilla que incluye una subconsulta.  En caso de que nuestras necesidades de datos se vuelvan m\u00e1s complejas, la consulta puede modificarse sin que aumente significativamente su tama\u00f1o o complejidad.<\/p>\n<p>Veamos nuestro otro modelo de base de datos.  Abra el proyecto\u00a0<strong>modelos\/estudiante.js<\/strong> e incluya el siguiente c\u00f3digo JavaScript:<\/p>\n<pre class=\"lang:js decode:true\">var Uuid = require(\"uuid\");\r\nvar Bucket = require(\"..\/..\/app\").bucket;\r\nvar N1qlQuery = require(\"couchbase\").N1qlQuery;\r\n\r\nfunction StudentModel() { };\r\n\r\nStudentModel.save = function(data, callback) {\r\n    data.id = Uuid.v4();\r\n    data.type = \"student\";\r\n    data.courses = [];\r\n    var statement = \"INSERT INTO `\" + Bucket._name + \"` (KEY, VALUE) VALUES ($1, $2) RETURNING `\" + Bucket._name + \"`.*\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    Bucket.query(query, [data.id, data], function(error, result) {\r\n        if(error) {\r\n            callback(error, null);\r\n            return;\r\n        }\r\n        callback(null, result);\r\n    });\r\n}\r\n\r\nStudentModel.updateCourses = function(id, courses, callback) {\r\n    var statement = \"UPDATE `\" + Bucket._name + \"` USE KEYS $1 SET courses = $2 RETURNING `\" + Bucket._name + \"`.*\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    Bucket.query(query, [id, courses], function(error, result) {\r\n        if(error) {\r\n            callback(error, null);\r\n            return;\r\n        }\r\n        callback(null, result);\r\n    });\r\n}\r\n\r\nStudentModel.getById = function(documentId, callback) {\r\n    var statement = \"SELECT t.id, t.type, t.firstname, t.lastname, t.address, \" +\r\n                    \"(SELECT s.* FROM `\" + Bucket._name + \"` AS s USE KEYS t.courses) AS courses \" +\r\n                    \"FROM `\" + Bucket._name + \"` AS t \" +\r\n                    \"WHERE t.type = 'student' AND t.id = $1\";\r\n    var query = N1qlQuery.fromString(statement);\r\n    Bucket.query(query, [documentId], function(error, result) {\r\n        if(error) {\r\n            console.log(error);\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n};\r\n\r\nStudentModel.getAll = function(callback) {\r\n    var statement = \"SELECT t.id, t.type, t.firstname, t.lastname, t.address, \" +\r\n                    \"(SELECT s.* FROM `\" + Bucket._name + \"` AS s USE KEYS t.courses) AS courses \" +\r\n                    \"FROM `\" + Bucket._name + \"` AS t \" +\r\n                    \"WHERE t.type = 'student'\";\r\n    var query = N1qlQuery.fromString(statement).consistency(N1qlQuery.Consistency.REQUEST_PLUS);\r\n    Bucket.query(query, function(error, result) {\r\n        if(error) {\r\n            return callback(error, null);\r\n        }\r\n        callback(null, result);\r\n    });\r\n};\r\n\r\nmodule.exports = StudentModel;<\/pre>\n<p>\u00bfLe resulta familiar?  Los dos modelos de bases de datos son similares porque los dos modelos de documentos son similares.  De nuevo, si la complejidad cambia, la capa de aplicaci\u00f3n seguir\u00e1 siendo f\u00e1cil de gestionar con consultas N1QL.<\/p>\n<p>Como las rutas API no tienen ninguna dependencia de la base de datos, el c\u00f3digo entre la aplicaci\u00f3n MongoDB y la aplicaci\u00f3n Couchbase puede ser compartido.  Para ser claros, me refiero a los archivos que se encuentran en el directorio\u00a0<strong>rutas<\/strong> directorio.<\/p>\n<h3>Arranque de la aplicaci\u00f3n y conexi\u00f3n a Couchbase<\/h3>\n<p>Con los endpoints en su lugar y los modelos de base de datos comunic\u00e1ndose a Couchbase a trav\u00e9s de N1QL, podemos terminar la aplicaci\u00f3n.<\/p>\n<p>Abra el archivo\u00a0<strong>app.js<\/strong> e incluya el siguiente c\u00f3digo JavaScript:<\/p>\n<pre class=\"lang:js decode:true\">var Couchbase = require(\"couchbase\");\r\nvar Express = require(\"express\");\r\nvar BodyParser = require(\"body-parser\");\r\n\r\nvar app = Express();\r\napp.use(BodyParser.json());\r\n\r\nmodule.exports.bucket = (new Couchbase.Cluster(\"couchbase:\/\/localhost\")).openBucket(\"example\");\r\nvar studentRoutes = require(\".\/couchbase\/routes\/students\")(app);\r\nvar courseRoutes = require(\".\/couchbase\/routes\/courses\")(app);\r\nvar server = app.listen(3000, function() {\r\n    console.log(\"Connected on port 3000...\");\r\n});<\/pre>\n<p>En el c\u00f3digo anterior estamos importando las dependencias que hab\u00edamos instalado e inicializando Express Framework.  Luego estamos estableciendo una conexi\u00f3n a la base de datos, juntando nuestras rutas e iniciando el servidor Node.js.<\/p>\n<p>Como estamos usando N1QL, no olvides crear al menos un \u00edndice en tu Couchbase Bucket.  Puede ser tan simple como lo siguiente:<\/p>\n<pre class=\"lang:default highlight:0 decode:true\">CREATE PRIMARY INDEX ON `ejemplo`;<\/pre>\n<p>En este punto deber\u00edas poder acceder a tu aplicaci\u00f3n de la misma forma que a MongoDB.  Visita https:\/\/localhost:3000 desde tu navegador web o con una herramienta como Postman o Fiddler.<\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>Acabas de ver c\u00f3mo tomar una aplicaci\u00f3n Node.js que utiliza MongoDB y el Lenguaje de Consulta MongoDB y convertirla a Couchbase con N1QL en su lugar.  Esta es una alternativa al <a href=\"https:\/\/www.couchbase.com\/blog\/es\/migrating-mongodb-mongoose-restful-api-couchbase-ottoman\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mongoose a Ottoman ODM<\/a> sobre la que escrib\u00ed anteriormente.<\/p>\n<p>Entonces, \u00bfpor qu\u00e9 querr\u00edas cambiar de MongoDB a Couchbase?  Bueno, Couchbase es mucho m\u00e1s r\u00e1pido y f\u00e1cil de escalar, pero N1QL tambi\u00e9n es incre\u00edblemente sencillo cuando se trabaja con datos complejos.  Podr\u00e1s reducir tu c\u00f3digo dr\u00e1sticamente y hacerlo m\u00e1s mantenible.  Echa un vistazo a la consulta Couchbase vs MongoDB <a href=\"https:\/\/www.couchbase.com\/blog\/es\/joining-nosql-documents-mongodb-query-language-vs-couchbase-n1ql\/\" target=\"_blank\" rel=\"noopener noreferrer\">tutorial<\/a> que escrib\u00ed en t\u00e9rminos de uni\u00f3n de datos entre las dos bases de datos.<\/p>\n<p>Para m\u00e1s informaci\u00f3n sobre c\u00f3mo usar Couchbase en una aplicaci\u00f3n Node.js:<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li>Echa un vistazo a la <a href=\"https:\/\/developer.couchbase.com\" target=\"_blank\" rel=\"noopener noreferrer\">Portal para desarrolladores de Couchbase<\/a>.<\/li>\n<li>Pruebe uno de los <a href=\"https:\/\/docs.couchbase.com\/server\/current\/develop\/integrations.html#ide-integrations\">IDEs para desarrolladores de Couchbase-JetBrains, VSCode<\/a>-para los que tenemos plugins.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>Customers often tell us they\u2019re preparing to migrate from MongoDB to Couchbase. They come, in part, because they\u2019re tired of the problems they\u2019ve experienced learning how to query MongoDB. Couchbase with N1QL provides a better alternative, especially for scaling up [&hellip;]<\/p>","protected":false},"author":63,"featured_media":2787,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1815,1816,1822,1812],"tags":[1393,1309,1745],"ppma_author":[9032],"class_list":["post-2918","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-couchbase-server","category-node-js","category-n1ql-query","tag-api","tag-mongodb","tag-restful"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Migrate From MongoDB to Couchbase with N1QL - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Learn how to take a Node.js application that uses MongoDB and the MongoDB Query Language and convert it to Couchbase with N1QL instead.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/migrate-mongodb-couchbase-n1ql\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Migrate From MongoDB to Couchbase with N1QL\" \/>\n<meta property=\"og:description\" content=\"Learn how to take a Node.js application that uses MongoDB and the MongoDB Query Language and convert it to Couchbase with N1QL instead.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/migrate-mongodb-couchbase-n1ql\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2017-03-07T19:11:30+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T00:33:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"389\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Migrate From MongoDB to Couchbase with N1QL\",\"datePublished\":\"2017-03-07T19:11:30+00:00\",\"dateModified\":\"2025-06-14T00:33:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/\"},\"wordCount\":2176,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png\",\"keywords\":[\"API\",\"mongodb\",\"restful\"],\"articleSection\":[\"Best Practices and Tutorials\",\"Couchbase Server\",\"Node.js\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/\",\"name\":\"Migrate From MongoDB to Couchbase with N1QL - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png\",\"datePublished\":\"2017-03-07T19:11:30+00:00\",\"dateModified\":\"2025-06-14T00:33:05+00:00\",\"description\":\"Learn how to take a Node.js application that uses MongoDB and the MongoDB Query Language and convert it to Couchbase with N1QL instead.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png\",\"width\":1100,\"height\":389},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Migrate From MongoDB to Couchbase with N1QL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\/\/www.thepolyglotdeveloper.com\",\"https:\/\/www.facebook.com\/thepolyglotdeveloper\",\"https:\/\/x.com\/nraboy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/es\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Migrar de MongoDB a Couchbase con N1QL - El blog de Couchbase","description":"Aprende c\u00f3mo tomar una aplicaci\u00f3n Node.js que usa MongoDB y el Lenguaje de Consulta MongoDB y convertirla a Couchbase con N1QL en su lugar.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/migrate-mongodb-couchbase-n1ql\/","og_locale":"es_MX","og_type":"article","og_title":"Migrate From MongoDB to Couchbase with N1QL","og_description":"Learn how to take a Node.js application that uses MongoDB and the MongoDB Query Language and convert it to Couchbase with N1QL instead.","og_url":"https:\/\/www.couchbase.com\/blog\/es\/migrate-mongodb-couchbase-n1ql\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2017-03-07T19:11:30+00:00","article_modified_time":"2025-06-14T00:33:05+00:00","og_image":[{"width":1100,"height":389,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png","type":"image\/png"}],"author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"10 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Migrate From MongoDB to Couchbase with N1QL","datePublished":"2017-03-07T19:11:30+00:00","dateModified":"2025-06-14T00:33:05+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/"},"wordCount":2176,"commentCount":1,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png","keywords":["API","mongodb","restful"],"articleSection":["Best Practices and Tutorials","Couchbase Server","Node.js","SQL++ \/ N1QL Query"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/","url":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/","name":"Migrar de MongoDB a Couchbase con N1QL - El blog de Couchbase","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png","datePublished":"2017-03-07T19:11:30+00:00","dateModified":"2025-06-14T00:33:05+00:00","description":"Aprende c\u00f3mo tomar una aplicaci\u00f3n Node.js que usa MongoDB y el Lenguaje de Consulta MongoDB y convertirla a Couchbase con N1QL en su lugar.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/02\/mongo-to-couchbase.png","width":1100,"height":389},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/migrate-mongodb-couchbase-n1ql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Migrate From MongoDB to Couchbase with N1QL"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, Defensor del Desarrollador, Couchbase","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy es un defensor de las tecnolog\u00edas modernas de desarrollo web y m\u00f3vil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y m\u00f3vil m\u00e1s f\u00e1cil de entender.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/es\/author\/nic-raboy-2\/"}]}},"authors":[{"term_id":9032,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","first_name":"Nic","last_name":"Raboy","user_url":"https:\/\/www.thepolyglotdeveloper.com","author_category":"","description":"Nic Raboy es un defensor de las tecnolog\u00edas modernas de desarrollo web y m\u00f3vil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y m\u00f3vil m\u00e1s f\u00e1cil de entender."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/2918","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=2918"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/2918\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/2787"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=2918"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=2918"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=2918"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=2918"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}