Vytvoření REST API pomocí Express.js a MongoDB

Tento tutoriál je částí 5 z 5 této série.

  • Část 1:Minimální Node.js s Babel Setup
  • Část 2:Jak nastavit Express.js v Node.js
  • Část 3:Jak vytvořit REST API s Express.js v Node.js
  • Část 4:Nastavení MongoDB pomocí Mongoose v Express

Node + Express + MongoDB je výkonný technologický zásobník pro backendové aplikace, který nabízí operace CRUD. Poskytuje vám vše pro odhalení API (Express routes), pro přidání obchodní logiky (Express middleware a logiku v rámci Express routes) a pro použití skutečných dat s databází (MongoDB). Je ideální pro vytvoření technologického zásobníku MERN (MongoDB, Express, React, Node), MEAN (MongoDB, Express, Angular, Node) nebo MEVN (MongoDB, Express, Vue, Node). Vše, co by chybělo, je frontendová aplikace s React, Angular, Vue nebo něčím jiným. Ale to je na jinou sekci.

Tato část se nejprve zaměřuje na připojení MongoDB k Express pro naše REST API. Dříve jsme MongoDB nastavili v naší aplikaci Express.js a nasadili databázi počátečními daty, ale zatím jsme ji v Express pro RESTful API nepoužili. Nyní se chceme ujistit, že každá operace CRUD procházející tímto REST API čte nebo zapisuje z/do databáze MongoDB, spíše než abychom používali ukázková data, jak jsme to dělali dříve pro naše expresní trasy. Proto potřebujeme propojit naše expresní trasy do MongoDB přes Mongoose, abychom spojili oba světy.

V našem src/index.js tam, kde nastavujeme a spouštíme aplikaci Express s databází MongoDB, již máme na místě expresní middleware, který předává modely jako kontext všem našim expresním trasám. Dříve byly tyto modely vzorovými daty. Nyní používáme modely Mongoose, které nás připojují k databázi MongoDB. Vzhledem k tomu, že struktura dat složek/souborů je stejná jako dříve, nic se nemění pro předávání modelů jako kontextu do expresních tras.

...
import models from './models';
const app = express();
...
app.use((req, res, next) => {  req.context = {    models,    me: models.users[1],  };  next();});
...

Uživatele me (autentizovaný uživatel) však lze získat z nasazených dat z databáze. Neexistuje žádný users pole již dostupné jako ukázková data na objektu modelů, protože modely jsou nyní naším rozhraním k databázi MongoDB.

...
import models from './models';
const app = express();
...
app.use(async (req, res, next) => {  req.context = {    models,    me: await models.User.findByLogin('rwieruch'),  };  next();});
...

I když zatím neznáme ověřeného uživatele, protože pro něj nepředáváme žádná data do REST API zvenčí, vezmeme pouze každého uživatele, o kterém víme, že v naší databázi existuje, kvůli předchozímu nasazování databáze MongoDB. findByLogin metoda je na našem modelu dostupná, protože jsme ji dříve implementovali jako vlastní metodu pro získávání uživatelů podle uživatelského jména nebo e-mailu.

Pojďme se nyní ponořit do našich expresních tras. Máme trasy pro relaci, uživatele a entitu zprávy. Entita relace je na prvním místě. Opět, místo použití ukázkových dat, která byla na modelech k dispozici dříve, můžeme k interakci s databází nyní použít rozhraní modelů – poháněné Mongoose. V souboru src/routes/session.js změňte následující řádky kódu:

import { Router } from 'express';
const router = Router();
router.get('/', async (req, res) => {  const user = await req.context.models.User.findById(    req.context.me.id,  );  return res.send(user);});
export default router;

Funkce route se stává asynchronní funkcí, protože nyní řešíme asynchronní požadavek na databázi MongoDB. Asynchronní povahu funkce řešíme pomocí async/await.

Vzhledem k tomu, že dříve jsme modely pohodlně předávali přes objekt kontextu do každé expresní cesty s aplikačním Express middlewarem, můžeme toho využít zde. Ověřeného uživatele, kterého jsme dříve libovolně převzali z databáze MongoDB, lze použít k načtení aktuálního uživatele relace z databáze.

Pojďme se vypořádat s uživatelskými trasami v src/routes/user.js soubor, který nabízí koncové body RESTful API pro načítání uživatelů nebo jednoho uživatele podle id. Oba požadavky API by měly vést k operacím čtení pro databázi MongoDB:

import { Router } from 'express';
const router = Router();
router.get('/', async (req, res) => {  const users = await req.context.models.User.find();  return res.send(users);});
router.get('/:userId', async (req, res) => {  const user = await req.context.models.User.findById(    req.params.userId,  );  return res.send(user);});
export default router;

První koncový bod API, který načte seznam uživatelů, nezíská z požadavku žádné vstupní parametry. Ale druhý koncový bod API má přístup k identifikátoru uživatele, aby mohl číst správného uživatele z databáze MongoDB.

V neposlední řadě, směrování zpráv v src/routes/message.js soubor. Kromě čtení zpráv a jedné zprávy podle identifikátoru máme také koncové body API pro vytváření zprávy a mazání zprávy. Obě operace by měly vést k operacím zápisu pro databázi MongoDB:

import { Router } from 'express';
const router = Router();
router.get('/', async (req, res) => {  const messages = await req.context.models.Message.find();  return res.send(messages);});
router.get('/:messageId', async (req, res) => {  const message = await req.context.models.Message.findById(    req.params.messageId,  );  return res.send(message);});
router.post('/', async (req, res) => {  const message = await req.context.models.Message.create({    text: req.body.text,    user: req.context.me.id,  });
  return res.send(message);});
router.delete('/:messageId', async (req, res) => {  const message = await req.context.models.Message.findById(    req.params.messageId,  );
  if (message) {    await message.remove();  }
  return res.send(message);});
export default router;

Existují kratší způsoby, jak provést odstranění zprávy v databázi pomocí Mongoose. Pokud však půjdete tímto způsobem, zajistíte spuštění databázových háčků, které lze v modelech nastavit. Nastavili jste jeden z těchto háčků, háček pro odstranění, v src/models/user.js soubor dříve:

...
userSchema.pre('remove', function(next) {  this.model('Message').deleteMany({ user: this._id }, next);});
...

Pokaždé, když je uživatel smazán, tento háček zajišťuje, že jsou smazány také všechny zprávy, které patří tomuto uživateli. Díky tomu se nemusíte starat o správné vyčištění databáze při každé operaci odstranění entity.

V podstatě to je vše pro připojení MongoDB k expresním trasám s Mongoose. Všechny modely nastavené pomocí Mongoose lze použít jako rozhraní k vaší databázi MongoDB. Jakmile uživatel narazí na vaše REST API, můžete provádět operace čtení nebo zápisu v expresních trasách do vaší databáze MongoDB.

Cvičení

  • Potvrďte zdrojový kód pro poslední sekci. Uvědomte si, že projekt nemůže správně běžet v karanténě, protože neexistuje žádná databáze.
    • Potvrďte změny z poslední sekce.
  • Zkontrolujte zdrojový kód alternativní implementace PostgreSQL s implementací Sequelize.
  • Experimentujte s vaším REST API s operacemi cURL.

Tento tutoriál je částí 1 ze 2 této série.

  • Část 2:Jak zacházet s chybami v Express