Build a Node.js app with MongoDB Flex
Diese Seite ist noch nicht in deiner Sprache verfügbar. Englische Seite aufrufen
In this tutorial, you implement a real world scenario with MongoDB Flex. After finishing all the steps, you have a Node.js app, which stores its data into a MongoDB Flex database. You learn how to connect a Node.js application to MongoDB Flex and why MongoDB works so well with JavaScript applications. With the acquired knowledge you can for instance build a REST- or GraphQL-API which is backed up by a solid and flexible database.
Overview
Section titled “Overview”This tutorial is split into the following sections:
- Create a MongoDB Flex instance with a user, proper rights and ACL settings.
- Initialize an environment to execute Node.js with the needed npm packages.
- Write a small Node.js application which tests the connection to the database.
- Create a Node.js application which is backed up by MongoDB Flex.
Prerequisites
Section titled “Prerequisites”- You have a STACKIT customer account: Create a customer account
- You have a STACKIT user account: Create a user account
- You have a STACKIT project: Create a project
- On the development system you have access to a shell with Node.js available.
- You can reach the STACKIT cloud from your development machine.
- You know the external IPv4 address of your client system.
Create a MongoDB Flex instance with a user, proper rights and ACL settings
Section titled “Create a MongoDB Flex instance with a user, proper rights and ACL settings”Initialize an environment to execute Node.js with the needed npm packages
Section titled “Initialize an environment to execute Node.js with the needed npm packages”At first, check, if you have a recent version of Node.js installed.
node --versionThe output should be something like this:
v24.4.1The installed version should be at least equal or bigger than v20.0.0. If you have an older version installed, please consult the manual of your system to install a more recent version.
After checking this prerequisite, create a folder for this tutorial:
mkdir nodejs-with-mongodb-flex-tutorialcd nodejs-with-mongodb-flex-tutorialnpm init -ynpm install mongodb dotenvThe output should be something like this:
added 13 packages, and audited 14 packages in 1s
1 package is looking for funding run `npm fund` for details
found 0 vulnerabilitiesPlease note that you can make adjustments to the created package.json. E.g. to adjust the initial version number, license or the author. Now you are ready to write your small Node.js test application.
Write a small Node.js application which tests the connection to the database
Section titled “Write a small Node.js application which tests the connection to the database”Open your code editor of choice and create a file called .env with the following content (insert the connection string which you saved before):
MONGODB_URI=mongodb://USERNAME:YOUR-SECRET-PASSWORD@s-f47ac10b-58cc-4372-a567-0e02b2c3d479-0.mongodb.eu01.onstackit.cloud:27017/default?authSource=default&tls=true&authMechanism=SCRAM-SHA-256Create another file called test-connection.mjs:
import { MongoClient } from "mongodb";import dotenv from "dotenv";
dotenv.config();
const uri = process.env.MONGODB_URI;
async function testConnection() { if (!uri) { console.error("MONGODB_URI not set!"); return; }
const client = new MongoClient(uri);
try { console.log("Connecting to MongoDB Flex...");
await client.connect();
await client.db("admin").command({ ping: 1 });
console.log("Succesfully conntected!");
const dbName = client.db().databaseName; console.log(`Connected to: ${dbName}`); } catch (error) { console.error("Error while connecting to MongoDB Flex:", error.message); } finally { await client.close(); console.log("Connection closed."); }}
testConnection();Now execute the mini application with your Node.JS interpreter:
node test-connection.mjsCreate a Node.js application which is backed up by MongoDB Flex
Section titled “Create a Node.js application which is backed up by MongoDB Flex”Now that you set up everything correctly, you can begin with the implementation of the actual application. At first we need to install further dependencies:
npm install expressYou should see something like:
added 67 packages, and audited 81 packages in 2s
15 packages are looking for funding run `npm fund` for details
found 0 vulnerabilitiesFor the sake of simplicity, we will not be setting up the recommended best practice Node.js folder structure in this tutorial. We recommend to follow this best practice structure when creating a project for production usage.
Create a file called main.mjs:
import express from "express";import { MongoClient } from "mongodb";import dotenv from "dotenv";
// Route-Importsimport booksRoutes from "./books.mjs";import searchRoutes from "./search.mjs";
// Loading .env file
dotenv.config();
const app = express();const port = process.env.PORT || 3000;const uri = process.env.MONGODB_URI;
// Middlewareapp.use(express.json());
// MongoDB clientlet db;
// Set up connection to databaseasync function connectToMongoDB() { try { const client = new MongoClient(uri); await client.connect(); db = client.db("buchverwaltung"); console.log("Connected to MongoDB Flex");
app.locals.db = db; } catch (error) { console.error("Connection error with MongoDB", error); process.exit(1); }}
// Routesapp.use("/api/books", booksRoutes);
// Health checkapp.get("/health", (req, res) => { res.json({ success: true, message: "API läuft", timestamp: new Date().toISOString(), });});
// 404 handlerapp.use("*", (req, res) => { res.status(404).json({ success: false, message: "Endpoint nicht gefunden", });});
// Error handlerapp.use((error, req, res, next) => { console.error(error.stack); res.status(500).json({ success: false, message: "Interner Serverfehler", });});
// Start serverasync function startServer() { await connectToMongoDB();
app.listen(port, () => { console.log(`🚀 Server läuft auf http://localhost:${port}`); console.log(`📚 API Endpunkte:`); console.log(` GET /api/books - All Books`); console.log(` POST /api/books - Neues Buch`); console.log(` GET /api/search?q=term - Bücher suchen`); });}
startServer().catch(console.error);Create a file called books.mjs:
import express from "express";import { ObjectId } from "mongodb";
const router = express.Router();
// Helper function for validationfunction validateBook(book) { const errors = []; if (!book.titel || book.titel.trim() === "") { errors.push("Titel ist erforderlich"); } if (!book.autor || book.autor.trim() === "") { errors.push("Autor ist erforderlich"); } if (book.seiten && (isNaN(book.seiten) || book.seiten <= 0)) { errors.push("Seitenzahl muss eine positive Zahl sein"); } return errors;}
// GET /api/books - get all booksrouter.get("/", async (req, res) => { try { const db = req.app.locals.db; const books = await db.collection("books").find({}).toArray();
res.json({ success: true, count: books.length, data: books, }); } catch (error) { res.status(500).json({ success: false, message: "Fehler beim Abrufen der Bücher", error: error.message, }); }});
// POST /api/books - Add new bookrouter.post("/", async (req, res) => { try { const db = req.app.locals.db; const bookData = req.body;
// Validation const errors = validateBook(bookData); if (errors.length > 0) { return res.status(400).json({ success: false, message: "Validierungsfehler", errors: errors, }); }
// Create book object const newBook = { titel: bookData.titel.trim(), autor: bookData.autor.trim(), isbn: bookData.isbn || null, seiten: bookData.seiten || null, genre: bookData.genre || null, erscheinungsjahr: bookData.erscheinungsjahr || null, beschreibung: bookData.beschreibung || null, erstelltAm: new Date(), aktualisiertAm: new Date(), };
const result = await db.collection("books").insertOne(newBook);
res.status(201).json({ success: true, message: "Buch erfolgreich hinzugefügt", data: { _id: result.insertedId, ...newBook }, }); } catch (error) { res.status(500).json({ success: false, message: "Fehler beim Hinzufügen des Buchs", error: error.message, }); }});
export default router;Create a file called search.mjs:
import express from "express";
const router = express.Router();
// GET /api/search?q=suchbegriff - search for booksrouter.get("/", async (req, res) => { try { const db = req.app.locals.db; const { q } = req.query;
if (!q || q.trim() === "") { return res.status(400).json({ success: false, message: "Suchbegriff ist erforderlich", }); }
const searchRegex = new RegExp(q.trim(), "i"); // case-insensitive search
const books = await db .collection("books") .find({ $or: [ { titel: searchRegex }, { autor: searchRegex }, { genre: searchRegex }, { beschreibung: searchRegex }, ], }) .toArray();
res.json({ success: true, count: books.length, searchTerm: q.trim(), data: books, }); } catch (error) { res.status(500).json({ success: false, message: "Fehler bei der Suche", error: error.message, }); }});
// GET /api/search/genre/:genre - filter books for genrerouter.get("/genre/:genre", async (req, res) => { try { const db = req.app.locals.db; const { genre } = req.params; const genreRegex = new RegExp(genre, "i");
const books = await db.collection("books").find({ genre: genreRegex }).toArray();
res.json({ success: true, count: books.length, genre: genre, data: books, }); } catch (error) { res.status(500).json({ success: false, message: "Fehler beim Filtern nach Genre", error: error.message, }); }});
// GET /api/search/autor/:autor - filter books for authorrouter.get("/autor/:autor", async (req, res) => { try { const db = req.app.locals.db; const { autor } = req.params; const autorRegex = new RegExp(autor, "i");
const books = await db.collection("books").find({ autor: autorRegex }).toArray();
res.json({ success: true, count: books.length, autor: autor, data: books, }); } catch (error) { res.status(500).json({ success: false, message: "Fehler beim Filtern nach Autor", error: error.message, }); }});
// GET /api/search/jahr/:jahr - filter books for release daterouter.get("/jahr/:jahr", async (req, res) => { try { const db = req.app.locals.db; const { jahr } = req.params; const jahrNum = parseInt(jahr);
if (isNaN(jahrNum)) { return res.status(400).json({ success: false, message: "Ungültiges Jahr", }); }
const books = await db.collection("books").find({ erscheinungsjahr: jahrNum }).toArray();
res.json({ success: true, count: books.length, jahr: jahrNum, data: books, }); } catch (error) { res.status(500).json({ success: false, message: "Fehler beim Filtern nach Jahr", error: error.message, }); }});
export default router;