Ir al contenido principal

Crea un gestor de tareas sencillo con categorías usando Node.js y MongoDB

Aprende a organizar tareas por categoría con Node.js y MongoDB. Crea una API REST con endpoints para crear, listar, obtener, actualizar y eliminar, y filtro por categoría.
Actualizado 10 sept 2026  · 10 min leer

Explorar con IA

ChatGPTClaudePerplexity

Una lista de tareas básica va de lujo al principio: añades tareas y las marcas como hechas cuando terminas. Pero a medida que crecen, se vuelve incómoda. Una solución muy útil es añadir categorías, para que cada tarea pertenezca a "Work", "Study", "Personal", etc., y puedas filtrar la lista por la categoría que te interese.

En este tutorial aprenderás a crear una API REST que te permita organizar tareas por categoría usando Node.js y MongoDB. Al final tendrás un servidor Node.js funcional con cinco endpoints: crear, listar, obtener, actualizar y eliminar, además de un filtro por categoría. También verás cómo aplicar validación de categorías usando el driver nativo de MongoDB, sin depender de un ODM como Mongoose.

Qué aprenderás

  • Cómo crear una API REST con Node.js, Express y MongoDB, incluyendo endpoints CRUD completos
  • Cómo validar la entrada, forzar categorías y gestionar con seguridad valores de ObjectId de forma eficaz
  • Cómo estructurar y probar tu API y luego conectarla a un frontend

Puedes encontrar el código completo de este tutorial en GitHub si prefieres clonarlo e ir leyendo sobre la marcha.

Requisitos previos

Antes de empezar, deberías tener:

  • Node.js 18+ instalado (npm se incluye por defecto)
  • MongoDB en local o un clúster gratuito de MongoDB Atlas
  • Postman o cualquier cliente HTTP
  • Conocimientos básicos de JavaScript y conceptos REST

Paso 1: prepara el proyecto

Vamos a construir nuestro gestor de tareas sencillo. Lo primero será crear una carpeta nueva e inicializar un proyecto de Node ejecutando estos comandos en la terminal:

mkdir task-manager-categories
cd task-manager-categories
npm init -y

A continuación, instalaremos cuatro dependencias de ejecución que necesita la app: express para el enrutado, el driver oficial de MongoDB, dotenv para cargar variables de entorno y, por último, helmet para las cabeceras de seguridad.

npm install express mongodb dotenv helmet

Para desarrollo, instala nodemon como dependencia de desarrollo con el siguiente comando para que el servidor se recargue automáticamente cuando cambien los archivos:

npm install --save-dev nodemon

Ahora abre la carpeta del proyecto en tu IDE y actualiza la sección scripts en package.json para incluir lo siguiente. Así podrás iniciar el servidor con npm start o ejecutarlo en modo desarrollo con npm run dev:

"scripts": {
  "start": "node server.js",
  "dev": "nodemon server.js"
}

Esta es la estructura que iremos montando. Cada carpeta tiene un rol claro: db/ gestiona la conexión a la base de datos, lib/ contiene funciones de ayuda, middleware/ es para el middleware de Express y routes/ define los controladores de las peticiones. La carpeta public/ alojará un pequeño frontend que añadiremos después. Incluso en un proyecto pequeño, esta estructura hace que todo sea fácil de seguir y deja claro dónde debe ir el nuevo código. Si quieres, crea ya el árbol de carpetas y ve completándolo sobre la marcha, o sáltatelo y añade cada archivo según avancemos:

task-manager-categories/
├── db/
│ └── connect.js
├── lib/
│ └── taskDocument.js
├── middleware/
│ └── parseObjectId.js
├── routes/
│ └── tasks.js
├── public/
│ ├── index.html
│ ├── styles.css
│ └── app.js
├── .env
├── .env.example
├── .gitignore
├── package.json
└── server.js

Paso 2: conecta con MongoDB

Para guardar y recuperar tareas, primero necesitamos conectar la app a MongoDB. Esto se hace con una cadena de conexión, que indica al driver cómo conectarse a tu base de datos. En lugar de ponerla a fuego en el código, es mejor guardarla en un archivo de entorno. Así mantienes fuera del repositorio los valores sensibles y te resulta más fácil cambiar de entorno.

Crea un archivo .env.example para documentar las variables necesarias y un .env con tus valores reales, así:

# Copia este archivo a `.env` y rellena los valores reales.

# --- MongoDB local ---
# Usa esto si ejecutas MongoDB en tu máquina
MONGO_URI=mongodb://127.0.0.1:27017

# --- MongoDB Atlas ---
# Sustituye <username>, <password> y <cluster-url> por tus valores reales
# Ejemplo: mongodb+srv://user:pass@cluster0.abcde.mongodb.net/
# MONGO_URI=mongodb+srv://<username>:<password>@<cluster-url>/?retryWrites=true&w=majority

DB_NAME=taskmanager
PORT=3000

Con la cadena de conexión lista, ya podemos usarla para configurar la conexión a MongoDB. Crea el archivo db/connect.js. Aquí inicializaremos el cliente de MongoDB y lo dejaremos disponible para el resto de la app:

const { MongoClient } = require("mongodb");

let client;
let db;

async function connectDB() {
  if (!process.env.MONGO_URI) {
    throw new Error("MONGO_URI is not set. Check your .env file.");
  }
  client = new MongoClient(process.env.MONGO_URI, {
    appName: "devrel-tutorial-javascript-crud-geeksforgeeks",
  });
  await client.connect();
  db = client.db(process.env.DB_NAME || "taskmanager");
  await db.collection("tasks").createIndex({ category: 1 });

  console.log(`MongoDB connected (db: ${db.databaseName})`);
}

function getTasksCollection() {
  if (!db) {
    throw new Error("Database not initialized. Call connectDB() first.");
  }
  return db.collection("tasks");
}

async function closeDB() {
  if (client) await client.close();
}

module.exports = { connectDB, getTasksCollection, closeDB };

Este archivo configura un único cliente de MongoDB que reutiliza el resto de la app. Solo quieres crearlo una vez, ya que el driver gestiona internamente el pool de conexiones. Crear un cliente nuevo en cada petición puede parecer inofensivo al principio, pero te traerá problemas de rendimiento muy pronto.

Paso 3: define la estructura de la tarea y la validación

A estas alturas, la app ya puede conectarse a MongoDB. Ahora necesitamos definir cómo es una tarea antes de empezar a guardar nada.

Aquí es donde usar el driver nativo de MongoDB se siente un poco diferente. No hay un archivo de esquema como con Mongoose. En su lugar, el "esquema" es simplemente la forma del objeto que insertas en la base de datos. Puede parecer algo laxo al principio, pero es útil porque te mantiene cerca de cómo funciona realmente MongoDB, sin capas de abstracción.

Aun así queremos validación. En lugar de repartir esa lógica por distintas rutas, la centralizaremos en un único sitio para que todo siga las mismas reglas. Crea un archivo llamado lib/taskDocument.js y añade el siguiente código:

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = 'ValidationError';
  }
}

const ALLOWED_CATEGORIES = ['Work', 'Personal', 'Study', 'Other'];

function assertValidCategory(category) {
  if (!ALLOWED_CATEGORIES.includes(category)) {
    throw new ValidationError(
      `category must be one of: ${ALLOWED_CATEGORIES.join(', ')}`
    );
  }
}

function buildTaskDocument(body = {}) {
  if (!body.title || typeof body.title !== 'string' || !body.title.trim()) {
    throw new ValidationError('title is required and must be a non-empty string');
  }
  if (body.category != null) {
    assertValidCategory(body.category);
  }
  const now = new Date();
  return {
    title: body.title.trim(),
    description: typeof body.description === 'string' ? body.description.trim() : '',
    category: body.category != null ? body.category : 'Other',
    completed: Boolean(body.completed),
    createdAt: now,
    updatedAt: now
  };
}

function buildTaskUpdate(body = {}) {
  const updates = {};
  if (typeof body.title === 'string' && body.title.trim()) {
    updates.title = body.title.trim();
  }
  if (typeof body.description === 'string') {
    updates.description = body.description.trim();
  }
  if (body.category != null) {
    assertValidCategory(body.category);
    updates.category = body.category;
  }
  if (body.completed != null) {
    updates.completed = Boolean(body.completed);
  }
  if (Object.keys(updates).length === 0) {
    throw new ValidationError('no valid fields provided for update');
  }
  updates.updatedAt = new Date();
  return updates;
}

module.exports = {
  ALLOWED_CATEGORIES,
  buildTaskDocument,
  buildTaskUpdate,
  ValidationError
};

Este archivo actúa como guardián de todo lo que entra en tu base de datos. Todas las peticiones de creación o actualización pasan por aquí, así que las reglas se aplican siempre en el mismo sitio.

Garantiza que las tareas tengan siempre la forma correcta, mantiene las categorías coherentes y evita sorpresas cuando empieces a hacer consultas. La clase personalizada ValidationError también te permite separar entradas inválidas de errores reales del servidor, para que tu API responda adecuadamente. Con esto en su sitio, el resto de la app puede mantenerse simple. Cada ruta se centra en su trabajo sabiendo que los datos ya son válidos. A continuación, conectaremos las rutas y empezaremos a guardar tareas en MongoDB.

Paso 4: gestiona ObjectId y la validación de peticiones

Ya sabemos cómo es una tarea; ahora veamos cómo la referenciamos. Siempre que una ruta incluya un parámetro :id, este llega como una cadena. Pero MongoDB espera un ObjectId. Si la cadena está mal formada, el driver lanza un error poco útil. En vez de manejarlo en cada ruta, lo centralizaremos con middleware para que todos los endpoints se comporten igual.

Para ello, crea un archivo llamado middleware/parseObjectId.js y añade lo siguiente:

const { ObjectId } = require('mongodb');

function parseObjectId(req, res, next) {
  const { id } = req.params;
  if (!ObjectId.isValid(id)) {
    return res.status(400).json({ error: 'invalid task id' });
  }
  req.taskId = new ObjectId(id);
  next();
}

module.exports = parseObjectId;

Este middleware se ejecuta antes del manejador de la ruta. Comprueba que el id es válido, lo convierte en un ObjectId y lo adjunta a req.taskId. Así, cuando se ejecute la lógica de la ruta, siempre trabajarás con un ObjectId correcto, y las entradas erróneas se rechazan pronto con una respuesta 400. Ahora lo conectaremos a nuestras rutas para dejarlo todo listo.

Paso 5: crea las rutas de tareas (CRUD + filtrado)

A estas alturas, ya hemos hecho lo más importante. Hemos definido cómo debe ser una tarea válida y hemos resuelto cómo analizar y validar los IDs. Eso permite que los manejadores de rutas se centren en una sola cosa: hablar con la base de datos.

Vamos a crear las rutas de la API en un archivo llamado routes/tasks.js y añadir lo siguiente:

const express = require('express');
const { getTasksCollection } = require('../db/connect');
const {
  ALLOWED_CATEGORIES,
  buildTaskDocument,
  buildTaskUpdate,
  ValidationError
} = require('../lib/taskDocument');
const parseObjectId = require('../middleware/parseObjectId');

const router = express.Router();

// POST /tasks
router.post('/', async (req, res, next) => {
  try {
    const doc = buildTaskDocument(req.body);
    const result = await getTasksCollection().insertOne(doc);
    res.status(201).json({ _id: result.insertedId, ...doc });
  } catch (err) {
    if (err instanceof ValidationError) {
      return res.status(400).json({ error: err.message });
    }
    next(err);
  }
});

// GET /tasks (optionally ?category=Work)
router.get('/', async (req, res, next) => {
  try {
    const { category } = req.query;
    if (category && !ALLOWED_CATEGORIES.includes(category)) {
      return res.status(400).json({
        error: `category must be one of: ${ALLOWED_CATEGORIES.join(', ')}`
      });
    }
    const filter = category ? { category } : {};
    const tasks = await getTasksCollection()
      .find(filter)
      .sort({ createdAt: -1 })
      .toArray();
    res.json(tasks);
  } catch (err) { next(err); }
});

// GET /tasks/:id
router.get('/:id', parseObjectId, async (req, res, next) => {
  try {
    const task = await getTasksCollection().findOne({ _id: req.taskId });
    if (!task) return res.status(404).json({ error: 'task not found' });
    res.json(task);
  } catch (err) { next(err); }
});

// PUT /tasks/:id
router.put('/:id', parseObjectId, async (req, res, next) => {
  try {
    const updates = buildTaskUpdate(req.body);
    const result = await getTasksCollection().findOneAndUpdate(
      { _id: req.taskId },
      { $set: updates },
      { returnDocument: 'after' }
    );
    if (!result) return res.status(404).json({ error: 'task not found' });
    res.json(result);
  } catch (err) {
    if (err instanceof ValidationError) {
      return res.status(400).json({ error: err.message });
    }
    next(err);
  }
});

// DELETE /tasks/:id
router.delete('/:id', parseObjectId, async (req, res, next) => {
  try {
    const result = await getTasksCollection().deleteOne({ _id: req.taskId });
    if (result.deletedCount === 0) {
      return res.status(404).json({ error: 'task not found' });
    }
    res.status(204).end();
  } catch (err) { next(err); }
});

module.exports = router;

Cada ruta del código anterior sigue el mismo patrón: toma la entrada de la petición, la pasa por los helpers que creamos, llama a MongoDB y devuelve una respuesta. Con la validación y el análisis del ID ya resueltos, el código aquí se mantiene pequeño y predecible. En la práctica, funciona así:

  • La ruta POST construye una nueva tarea con buildTaskDocument antes de insertarla
  • Las rutas GET filtran opcionalmente por categoría y devuelven los resultados ordenados de más nuevo a más antiguo
  • La ruta PUT usa buildTaskUpdate, así que las actualizaciones parciales son seguras y consistentes
  • La ruta DELETE elimina una tarea por su ObjectId ya analizado

También hay algunos detalles interesantes en este código:

  • find() devuelve un cursor, no un array, así que encadenamos .toArray() tras ordenar para obtener los resultados
  • findOneAndUpdate con returnDocument: 'after' te devuelve el documento actualizado al instante
  • Devolvemos códigos HTTP adecuados: 201 para crear, 204 para eliminar y 400 o 404 cuando corresponde
  • Los errores inesperados se pasan a next(err) para gestionarlos en un único sitio en lugar de repetir lógica en cada ruta

Paso 6: conecta todas las piezas en el servidor

Ya tenemos todas las piezas: validación, rutas limpias y conexión a base de datos. Ahora solo falta conectarlo todo e iniciar el servidor. Crea un archivo server.js. Es el punto de entrada de la app, donde todo se une:

require('dotenv').config();

const path = require('path');
const express = require('express');
const helmet = require('helmet');
const { connectDB, closeDB } = require('./db/connect');
const tasksRouter = require('./routes/tasks');

if (!process.env.MONGO_URI) {
  console.error('Fatal: MONGO_URI is not set. Copy .env.example to .env and fill it in.');
  process.exit(1);
}

const PORT = Number(process.env.PORT) || 3000;

const app = express();

app.use(helmet());
app.use(express.json({ limit: '100kb' }));
app.use(express.static(path.join(__dirname, 'public')));

app.get('/health', (req, res) => {
  res.json({ status: 'ok', service: 'task-manager-with-categories' });
});
app.use('/tasks', tasksRouter);

app.use((req, res) => {
  res.status(404).json({ error: 'not found' });
});

app.use((err, req, res, next) => {
  if (err.type === 'entity.too.large') {
    return res.status(413).json({ error: 'payload too large' });
  }
  if (err.type === 'entity.parse.failed') {
    return res.status(400).json({ error: 'invalid JSON body' });
  }
  console.error(err);
  res.status(500).json({ error: 'internal server error' });
});

async function start() {
  try {
    await connectDB();
    const server = app.listen(PORT, () => {
      console.log(`Server running on http://localhost:${PORT}`);
    });

    const shutdown = () => {
      console.log('\nShutting down gracefully...');
      server.close(async () => {
        await closeDB();
        process.exit(0);
      });
      setTimeout(() => process.exit(1), 10_000).unref();
    };
    process.on('SIGINT', shutdown);
    process.on('SIGTERM', shutdown);
  } catch (err) {
    console.error('Failed to start server:', err);
    process.exit(1);
  }
}

if (require.main === module) {
  start();
}

module.exports = { app, start };

Este archivo lo deja todo bien atado. Comprueba que las variables de entorno estén definidas antes de ejecutar nada, aplica seguridad básica con helmet y limita el JSON entrante para que tu app no acepte cargas enormes por error. También sirve la carpeta public/, para que el frontend viva en la misma app sin necesitar un servidor aparte.

Todas las rutas se montan bajo /tasks y cualquier cosa que no coincida devuelve un limpio 404. Los errores se gestionan en un único sitio en lugar de repetirse en cada ruta, lo que mantiene la consistencia y facilita el mantenimiento. La conexión a la base de datos se establece antes de que el servidor empiece a escuchar, así que nunca aceptas peticiones antes de estar listo, y el apagado es ordenado, cerrando las conexiones correctamente.

Ahora arráncalo para comprobar que todo funciona con npm run dev. Si todo está bien conectado, verás algo como esto:

MongoDB connected (db: taskmanager)
Server running on http://localhost:3000

¡Listo! Ya tenemos una API totalmente funcional, así que vamos a probarla.

Paso 7: prueba los endpoints de la API

Antes de construir una interfaz, conviene confirmar que cada endpoint funciona por separado. Esto facilita mucho el debug, porque puedes ver enseguida si el problema viene de la API o del frontend. Usaremos Postman (o cualquier cliente HTTP) y lanzaremos unas cuantas peticiones en orden. Cada una se apoya en los datos creados en el paso anterior.

Crea una tarea: Envía una petición POST con título, descripción y categoría. Si todo va bien, la API devuelve 201 Created con la nueva tarea y su _id generado.

POST http://localhost:3000/tasks
Content-Type: application/json

{
  "title": "Write GeeksForGeeks article",
  "description": "First draft by Friday",
  "category": "Work"
}

Crea unas cuantas más: Lanza la misma petición POST con cuerpos distintos para tener datos con los que probar el listado y el filtrado. Con esto tendrás un dataset pequeño para consultar.

{ "title": "Go for a run", "category": "Personal" }
{ "title": "Read MongoDB docs", "category": "Study" }
{ "title": "Buy groceries" } // category defaults to "Other"

Lista todas las tareas: Devuelve todas las tareas, ordenadas de la más reciente a la más antigua.

GET http://localhost:3000/tasks

Filtra por categoría: Devuelve solo las tareas de Work. El índice que añadiste antes mantiene esta consulta rápida a medida que crecen los datos.

GET http://localhost:3000/tasks?category=Work

Actualiza una tarea: Usa el _id de una de las tareas que acabas de crear (puedes copiarlo de la respuesta del POST o del endpoint de listado). Devuelve la tarea actualizada. Solo necesitas enviar los campos que quieras cambiar, así que las actualizaciones parciales se mantienen simples.

PUT http://localhost:3000/tasks/<paste-task-id-here>
Content-Type: application/json

{ "completed": true }

Elimina una tarea: Usa el _id de la tarea que quieras borrar. Devuelve 204 No Content. Si intentas obtener de nuevo esa tarea, recibirás un 404 con "task not found".

DELETE http://localhost:3000/tasks/<paste-task-id-here>

Con esto confirmas que todas las rutas se comportan como esperas. La API hace su trabajo, así que podemos pasar a construir una interfaz encima.

Paso 8: añade un frontend para interactuar con la API

Postman va genial para verificar la API, pero apetece verlo en una web real, así que añadiremos algo de código frontend a nuestra aplicación.

En lugar de pegar aquí archivos grandes de HTML y CSS, he subido el código a este repositorio de GitHub. Ve allí y copia el contenido de index.html, styles.css y favicon.svg en tu carpeta public/ del proyecto. Guarda los cambios y ve a localhost:3000. Luego pega el código de abajo en el archivo app.js:

const form = document.getElementById('task-form');
const titleEl = document.getElementById('title');
const descEl = document.getElementById('description');
const catEl = document.getElementById('category');
const errEl = document.getElementById('form-error');
const listEl = document.getElementById('task-list');
const emptyEl = document.getElementById('empty');
const filterEl = document.getElementById('filter');
const countEl = document.getElementById('task-count');

async function api(method, path, body) {
  const res = await fetch(path, {
    method,
    headers: body ? { 'Content-Type': 'application/json' } : {},
    body: body ? JSON.stringify(body) : undefined
  });

  if (res.status === 204) return null;

  const data = await res.json();
  if (!res.ok) throw new Error(data.error || `Request failed (${res.status})`);
  return data;
}

const fetchTasks = (category) =>
  api('GET', '/tasks' + (category ? `?category=${encodeURIComponent(category)}` : ''));

const createTask = (body) => api('POST', '/tasks', body);
const updateTask = (id, body) => api('PUT', `/tasks/${id}`, body);
const deleteTask = (id) => api('DELETE', `/tasks/${id}`);

function updateCount(tasks) {
  const active = tasks.filter((t) => !t.completed).length;
  const total = tasks.length;

  if (total === 0) {
    countEl.textContent = '';
    return;
  }

  const scope = filterEl.value ? ` in ${filterEl.value}` : '';
  countEl.textContent = `${total} tasks${scope} · ${active} active`;
}

function renderTask(task) {
  const li = document.createElement('li');
  li.className = 'task' + (task.completed ? ' completed' : '');

  const checkbox = document.createElement('input');
  checkbox.type = 'checkbox';
  checkbox.checked = task.completed;
  checkbox.addEventListener('change', () =>
    updateTask(task._id, { completed: checkbox.checked }).then(refresh)
  );

  const title = document.createElement('div');
  title.textContent = task.title;

  const badge = document.createElement('span');
  badge.textContent = task.category;

  const del = document.createElement('button');
  del.textContent = 'Delete';
  del.onclick = () => deleteTask(task._id).then(refresh);

  li.append(checkbox, title, badge, del);
  return li;
}

function render(tasks) {
  listEl.innerHTML = '';
  emptyEl.classList.toggle('hidden', tasks.length > 0);

  for (const task of tasks) {
    listEl.appendChild(renderTask(task));
  }

  updateCount(tasks);
}

async function refresh() {
  try {
    const tasks = await fetchTasks(filterEl.value);
    render(tasks);
  } catch (e) {
    errEl.textContent = e.message;
  }
}

form.addEventListener('submit', async (e) => {
  e.preventDefault();
  errEl.textContent = '';

  const title = titleEl.value.trim();
  if (!title) {
    errEl.textContent = 'Title is required.';
    return;
  }

  try {
    await createTask({
      title,
      description: descEl.value.trim(),
      category: catEl.value
    });

    form.reset();
    await refresh();
  } catch (e) {
    errEl.textContent = e.message;
  }
});

filterEl.addEventListener('change', refresh);

refresh();

Este JavaScript es donde todo vuelve a conectarse con la API que construiste. Cada función mapea a una de tus rutas, lo que mantiene el frontend fácil de seguir. Todas las peticiones pasan por un único helper api(), así que manejas los errores en un solo sitio en vez de repetir lógica por toda la app.

El filtrado funciona pasando una query string como ?category=Work, que se integra directamente con la lógica del backend que añadiste. Tras crear, actualizar o eliminar una tarea, la app vuelve a obtener la lista para mantener la UI sincronizada. El contador de tareas es un detalle pequeño, pero hace que la app se sienta más viva mientras la usas.

Reinicia ahora el servidor con npm run dev y abre http://localhost:3000 para probar el gestor de tareas. Añade unas cuantas, actualízalas, cambia entre categorías y borra alguna. A estas alturas, frontend y backend están conectados y funcionando de extremo a extremo.

Resumen

¡Enhorabuena! Has creado desde cero una API completa para un gestor de tareas con Node.js, Express y MongoDB. Has aplicado validación, mantenido rutas concisas y conectado todo en un sistema funcional. Lo más importante: te has mantenido cerca de cómo funciona realmente MongoDB, sin ocultarlo tras abstracciones. A partir de aquí puedes empezar a evolucionar la app para llevarla a producción.

Ideas clave

  • Usar middleware y centralizar la validación mantiene tu código limpio y predecible.
  • El driver nativo de MongoDB te da control sin abstracciones innecesarias.
  • Una API bien estructurada es fácil de ampliar hasta una app lista para producción.

FAQs

¿Necesito Mongoose para crear una API con MongoDB?

No. Este tutorial usa el driver nativo de MongoDB, que te da más control y mantiene todo ligero. Puedes añadir Mongoose más adelante si quieres abstracciones de esquema.

¿Cómo valido datos sin un esquema?

Puedes centralizar la validación en funciones helper (como buildTaskDocument), garantizando que todas las rutas apliquen las mismas reglas antes de escribir en la base de datos.

¿Qué pasa si paso un ObjectId no válido?

El middleware lo rechaza de forma temprana con una respuesta 400, evitando que MongoDB lance errores confusos.

Temas
MongoDB

Cursos destacados de DataCamp

Curso

Introducción a MongoDB en Python

3 h
24.2K
Aprende a manipular y analizar datos estructurados de forma flexible con MongoDB.
Ver detallesRight Arrow
Iniciar Curso
Ver másRight Arrow
Relacionado

blog

10 proyectos SQL listos para tu portafolio, aptos para todos los niveles

Selecciona tu primer proyecto SQL, o el siguiente, para practicar tus habilidades actuales en SQL, desarrollar otras nuevas y crear un portafolio profesional excepcional.
Elena Kosourova's photo

Elena Kosourova

11 min

blog

Los 13 mejores proyectos de AWS: De principiante a profesional

Explora 13 proyectos prácticos de AWS para todos los niveles. Mejora tus conocimientos sobre la nube con aplicaciones prácticas del mundo real y la orientación de expertos.
Joleen Bothma's photo

Joleen Bothma

12 min

Tutorial

Guía de modelado de datos de MongoDB para aplicaciones de blogs

Aprende algunas posibilidades de modelado de datos que incluyen documentos anidados al diseñar un sistema de gestión de contenidos (CMS) o una aplicación de blog.
Nic Raboy's photo

Nic Raboy

Tutorial

Desarrollo backend con Python: guía completa para principiantes

Esta guía completa te enseña los fundamentos del backend con Python. Aprende conceptos básicos, frameworks y buenas prácticas para empezar a crear aplicaciones web.
Oluseye Jeremiah's photo

Oluseye Jeremiah

15 min

Tutorial

Aprendizaje automático de datos categóricos con el tutorial de Python

Aprenda los trucos más comunes para manejar datos categóricos y preprocesarlos para construir modelos de aprendizaje automático.
Moez Ali's photo

Moez Ali

14 min

Tutorial

Base de datos Azure SQL: Configuración y gestión paso a paso

Aprende a crear, conectar, gestionar, consultar y proteger tu base de datos Azure SQL. Esta guía paso a paso cubre todo lo esencial para una configuración óptima de la base de datos.
Anneleen Rummens's photo

Anneleen Rummens

12 min

Ver MásVer Más