Menu
CoddyTech

Encontrando por ObjectId

Parte da seção Bancos de dados com MongoDB do Journey de Node.js da Coddy. Lição 7 de 29.

Para responder a uma consulta sobre um livro, o servidor o busca pelo _id, mas o id chega na URL como texto.

Um _id que o MongoDB cria é um ObjectId: um valor de 12 bytes escrito como 24 caracteres hexadecimais: os dígitos de 0 a 9 e as letras de a a f. O JSON o mostra como uma string, mas no banco de dados ele não é uma, então um filtro com o texto simples não encontra nada. Primeiro, transforme o texto em um ObjectId. ObjectId.isValid indica se um texto pode ser um, porque new ObjectId lança um erro para qualquer outra coisa.

import { ObjectId } from 'mongodb';

const text = '66f1c2a9e4b0a1b2c3d4e5f6';
await orders.findOne({ _id: new ObjectId(text) }); // o pedido, ou null
await orders.findOne({ _id: text });               // null: text não é um ObjectId
ObjectId.isValid('42');                            // false

findOne retorna o primeiro documento correspondente, ou null quando nenhum corresponde.

challenge icon

Desafio

Fácil

Esta etapa abre o projeto da API de estante de livros preparado para o curso, em vez dos arquivos do seu projeto de Inserindo documentos (incluindo server.js). Seu trabalho anterior continua na lição correspondente. Leia os arquivos fornecidos antes de editar server.js. Esta cópia contém as rotas para listar e inserir livros.

Um cliente quer um livro, escolhido pelo seu _id.

  1. Em server.js, adicione uma rota GET /books/:id.
  2. O id na URL é texto. Há textos que nunca podem ser um ObjectId, que tem 24 caracteres: dígitos e as letras de a a f. Para esse tipo de texto, responda com o status 400 e um erro, usando sendError, por exemplo { "error": "Not a valid id" }. Verifique isso antes de criar um ObjectId, porque criá-lo a partir de texto inválido gera um erro.
  3. Caso contrário, procure o livro pelo seu _id. Quando encontrá-lo, responda com o status 200 e o livro: { "_id": "6720a1f4c2b9e81d3a5f0c11", "title": "Dune", "author": "Frank Herbert", "year": 1965, "isbn": "9780441013593", "genre": "scifi" }.
  4. Quando nenhum livro tiver esse _id, responda com o status 404 e um erro, por exemplo { "error": "No such book" }. Experimente: envie GET /books e copie o _id de Dune: os 24 caracteres depois de "_id":. Cada vez que você clica em Executar, os livros recebem novos ids, então copie-o novamente após cada execução. Envie GET /books/ seguido pelo id que você copiou: você recebe 200 e Dune. Envie GET /books/42: você recebe 400. Envie GET /books/000000000000000000000000: é um id válido que nenhum livro tem, então você recebe 404.

Experimente você mesmo

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

// Todo erro retorna { 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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Bancos de dados com MongoDB

Pratique por conta própria: Playground de Express