Рассмотрим, как совместить Mongoose и Express и выполнять операции с данными, когда приходят те или иные запросы к серверу. Для этого определим следующий файл приложения app.js:
const mongoose = require("mongoose"); const express = require("express"); const Schema = mongoose.Schema; const app = express(); app.use(express.static("public")); app.use(express.json()); const userScheme = new Schema({name: String, age: Number}, {versionKey: false}); const User = mongoose.model("User", userScheme); async function main() { try{ await mongoose.connect("mongodb://127.0.0.1:27017/usersdb"); app.listen(3000); console.log("Сервер ожидает подключения..."); } catch(err) { return console.log(err); } } app.get("/api/users", async (req, res)=>{ // получаем всех пользователей const users = await User.find({}); res.send(users); }); app.get("/api/users/:id", async(req, res)=>{ const id = req.params.id; // получаем одного пользователя по id const user = await User.findById(id); if(user) res.send(user); else res.sendStatus(404); }); app.post("/api/users", jsonParser, async (req, res) =>{ if(!req.body) return res.sendStatus(400); const userName = req.body.name; const userAge = req.body.age; const user = new User({name: userName, age: userAge}); // сохраняем в бд await user.save(); res.send(user); }); app.delete("/api/users/:id", async(req, res)=>{ const id = req.params.id; // удаляем по id const user = await User.findByIdAndDelete(id); if(user) res.send(user); else res.sendStatus(404); }); app.put("/api/users", jsonParser, async (req, res)=>{ if(!req.body) return res.sendStatus(400); const id = req.body.id; const userName = req.body.name; const userAge = req.body.age; const newUser = {age: userAge, name: userName}; // обновляем данные пользователя по id const user = await User.findOneAndUpdate({_id: id}, newUser, {new: true}); if(user) res.send(user); else res.sendStatus(404); }); main(); // прослушиваем прерывание работы программы (ctrl-c) process.on("SIGINT", async() => { await mongoose.disconnect(); console.log("Приложение завершило работу"); process.exit(); });
По сути здесь производятся все те операции, которые были рассмотрены в прошлой теме. Единственное, что можно отметить, это запуск сервера после удачного подключения к базе данных usersdb в функции mongoose.connect:
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb"); app.listen(3000); console.log("Сервер ожидает подключения...");
Теперь создадим в папке проекта новый каталог "public" и определим в этом каталоге файл index.html:
В файле index.html определим следующий код:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>METANIT.COM</title> <style> td, th {padding:5px;min-width:90px;max-width:200px; text-align:start;} .btn {padding:4px; border:1px solid #333; background-color: #eee; border-radius: 2px; margin:5px; cursor:pointer;} </style> </head> <body> <h2>Список пользователей</h2> <form name="userForm"> <input type="hidden" name="id" value="0" /> <p> <label>Имя:</label><br> <input name="name" /> </p> <p> <label>Возраст:</label><br> <input name="age" type="number" /> </p> <p> <button id="submitBtn" type="submit">Сохранить</button> <button id="resetBtn">Сбросить</button> </p> </form> <table> <thead><tr><th>Id</th><th>Имя</th><th>Возраст</th><th></th></tr></thead> <tbody></tbody> </table> <script> const tbody = document.querySelector("tbody"); // Получение всех пользователей async function GetUsers() { // отправляет запрос и получаем ответ const response = await fetch("/api/users", { method: "GET", headers: { "Accept": "application/json" } }); // если запрос прошел нормально if (response.ok === true) { // получаем данные const users = await response.json(); users.forEach(user => { // добавляем полученные элементы в таблицу tbody.append(row(user)); }); } } // Получение одного пользователя async function GetUser(id) { const response = await fetch("/api/users/" + id, { method: "GET", headers: { "Accept": "application/json" } }); if (response.ok === true) { const user = await response.json(); const form = document.forms["userForm"]; form.elements["id"].value = user._id; form.elements["name"].value = user.name; form.elements["age"].value = user.age; } } // Добавление пользователя async function CreateUser(userName, userAge) { const response = await fetch("api/users", { method: "POST", headers: { "Accept": "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ name: userName, age: parseInt(userAge, 10) }) }); if (response.ok === true) { const user = await response.json(); reset(); tbody.append(row(user)); } } // Изменение пользователя async function EditUser(userId, userName, userAge) { const response = await fetch("api/users", { method: "PUT", headers: { "Accept": "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ id: userId, name: userName, age: parseInt(userAge, 10) }) }); if (response.ok === true) { const user = await response.json(); reset(); document.querySelector(`tr[data-rowid="${user._id}"]`).replaceWith(row(user)); } } // Удаление пользователя async function DeleteUser(id) { const response = await fetch("/api/users/" + id, { method: "DELETE", headers: { "Accept": "application/json" } }); if (response.ok === true) { const user = await response.json(); document.querySelector(`tr[data-rowid="${user._id}"]`).remove(); } } // сброс формы function reset() { const form = document.forms["userForm"]; console.log(form); form.reset(); form.elements["id"].value = 0; } // создание строки для таблицы function row(user) { const tr = document.createElement("tr"); tr.setAttribute("data-rowid", user._id); const idTd = document.createElement("td"); idTd.append(user._id); tr.append(idTd); const nameTd = document.createElement("td"); nameTd.append(user.name); tr.append(nameTd); const ageTd = document.createElement("td"); ageTd.append(user.age); tr.append(ageTd); const linksTd = document.createElement("td"); const editLink = document.createElement("a"); editLink.setAttribute("data-id", user._id); editLink.setAttribute("class", "btn"); editLink.append("Изменить"); editLink.addEventListener("click", e => { e.preventDefault(); GetUser(user._id); }); linksTd.append(editLink); const removeLink = document.createElement("a"); removeLink.setAttribute("data-id", user._id); removeLink.setAttribute("class", "btn"); removeLink.append("Удалить"); removeLink.addEventListener("click", e => { e.preventDefault(); DeleteUser(user._id); }); linksTd.append(removeLink); tr.appendChild(linksTd); return tr; } // сброс значений формы document.getElementById("resetBtn").addEventListener("click", e => { e.preventDefault(); reset(); }); // отправка формы document.forms["userForm"].addEventListener("submit", e => { e.preventDefault(); const form = document.forms["userForm"]; const id = form.elements["id"].value; const name = form.elements["name"].value; const age = form.elements["age"].value; if (id == 0) CreateUser(name, age); else EditUser(id, name, age); }); // загрузка пользователей GetUsers(); </script> </body> </html>
В принципе код index.html вкратце обсуждался в статье про создание API в Node.js, здесь же весь код практически повторяется.
И поскольку Express в качестве хранилища статических файлов использует папку public, то при обращении к приложению по корневому маршруту http://localhost:3000 клиент получит данный файл.
Запустим приложение, обратимся к приложению по адресу http://localhost:3000 и мы сможем взаимодействовать с базой данных MongoDB через Mongoose: