Menu
CoddyTech

Búsqueda por ObjectId

Parte de la sección Bases de datos con MongoDB del Journey de Node.js de Coddy. Lección 7 de 29.

Para obtener un libro, el servidor lo busca por _id, pero el id llega en la URL como texto.

Un _id que MongoDB crea es un ObjectId: un valor de 12 bytes escrito como 24 caracteres hexadecimales: los dígitos del 0 al 9 y las letras de la a a la f. JSON lo muestra como una cadena, pero en la base de datos no lo es, así que un filtro con el texto simple no encuentra nada. Primero, convierte el texto en un ObjectId. ObjectId.isValid indica si un texto puede serlo, porque new ObjectId genera un error con cualquier otra cosa.

import { ObjectId } from 'mongodb';

const text = '66f1c2a9e4b0a1b2c3d4e5f6';
await orders.findOne({ _id: new ObjectId(text) }); // el pedido, o null
await orders.findOne({ _id: text });               // null: text no es un ObjectId
ObjectId.isValid('42');                            // false

findOne devuelve el primer documento que coincide, o null cuando ninguno coincide.

challenge icon

Desafío

Fácil

Este paso abre el proyecto de API de estantería preparado para el curso, en lugar de los archivos de tu proyecto de Inserción de documentos (incluido server.js). Tu trabajo anterior permanece en su propia lección. Lee los archivos proporcionados antes de editar server.js. Esta copia contiene las rutas para listar e insertar libros.

Un cliente quiere un libro, elegido por su _id.

  1. En server.js, añade una ruta GET /books/:id.
  2. El id de la URL es texto. Hay textos que nunca pueden ser un ObjectId, que consta de 24 caracteres: dígitos y las letras de la a a la f. Para ese texto, responde con el estado 400 y un error, usando sendError, por ejemplo { "error": "Not a valid id" }. Compruébalo antes de crear un ObjectId, porque crearlo a partir de texto no válido provoca un error.
  3. En caso contrario, busca el libro por su _id. Cuando lo encuentres, responde con el estado 200 y el libro: { "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1965, "isbn": "9780441013593", "genre": "scifi" }.
  4. Si ningún libro tiene ese _id, responde con el estado 404 y un error, por ejemplo { "error": "No such book" }. Pruébalo: Envía GET /books y copia el _id de Dune: los 24 caracteres después de "_id":. Cada vez que ejecutes el código, los libros reciben ids nuevos, así que vuelve a copiarlo después de cada ejecución. Envía GET /books/ seguido del id que copiaste: obtendrás 200 y Dune. Envía GET /books/42: obtendrás 400. Envía GET /books/000000000000000000000000: es un id válido que ningún libro tiene, así que obtendrás 404.

Pruébalo tú mismo

import express from 'express';
import { MongoClient } from 'mongodb';

const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('shelf');
const books = db.collection('books');

await books.insertMany([
    { title: 'Dune', author: 'Frank Herbert', year: 1965, isbn: '9780441013593', genre: 'scifi' },
    { title: 'Kindred', author: 'Octavia E. Butler', year: 1979, isbn: '9780807083697', genre: 'scifi' },
    { title: 'Emma', author: 'Jane Austen', year: 1815, isbn: '9780141439587', genre: 'classic' },
]);

const app = express();
app.use(express.json());

// Cada error responde con { error: message }.
function sendError(res, status, message) {
    res.status(status).json({ error: message });
}

app.get('/', (req, res) => {
    res.send('Bookshelf API');
});

app.get('/books', async (req, res) => {
    const list = await books.find().toArray();
    res.json(list);
});

app.post('/books', async (req, res) => {
    const book = req.body;
    await books.insertOne(book);
    res.status(201).json(book);
});

app.listen(3000, () => {
    console.log('Bookshelf is running on port 3000');
});
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Bases de datos con MongoDB

Practica por tu cuenta: Playground de Express