diff --git a/README.md b/README.md index 35019cd8..c4b54b80 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,20 @@ # Project Mongo API -Replace this readme with your own information about your project. +Week 18th proyect. Build an API with Mongo DataBase. +This week's goal was very broad: +✓ How to create an API using Mongo DB. +✓ How to model data in Mongo using Mongoose +✓ How to store secret information such as database passwords +✓ How to return useful error messages from your API endpoints +✓ How to fetch items from a Mongo database using Mongoose +✓ How to seed large amounts of data to a database -Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. +All of the key objectives have been challenging, especially with large amounts of data like in this case, but I have learned a lot doing it. I decided to keep on Netflix films to see the differences between one API and the other. ## The problem -Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? +The most challenging issues that I had were the seeding of data and the error messages (as clear as possible). I am half way from adding styling but I don not have enough time to render it on time to meet the schedule. I'll do it just for fun. I really love API's and Data Bases! ## View it live -Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. +https://maryyy-ux-project-mongo-api.onrender.com diff --git a/models/NetflixModel.js b/models/NetflixModel.js new file mode 100644 index 00000000..2c57a5af --- /dev/null +++ b/models/NetflixModel.js @@ -0,0 +1,18 @@ +import mongoose from "mongoose"; + +const NetflixSchema = new mongoose.Schema({ + show_id: Number, + title: String, + director: String, + cast: String, + country: String, + date_added: String, + release_year: Number, + rating: String, + duration: String, + listed_in: String, + description: String, + type: String, +}); + +export const Netflix = mongoose.model("Netflix", NetflixSchema); diff --git a/package.json b/package.json index 6830a48a..c68bd712 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,21 @@ "name": "project-mongo-api", "version": "1.0.0", "description": "Starter project to get up and running with express quickly", + "main": "server.js", + "keywords": [], + "author": "", + "license": "ISC", "scripts": { "start": "babel-node server.js", "dev": "nodemon server.js --exec babel-node" }, - "author": "", - "license": "ISC", "dependencies": { - "@babel/core": "^7.17.9", - "@babel/node": "^7.16.8", - "@babel/preset-env": "^7.16.11", + "@babel/core": "^7.26.0", + "@babel/node": "^7.26.0", + "@babel/preset-env": "^7.26.0", "cors": "^2.8.5", - "express": "^4.17.3", - "mongoose": "^8.0.0", - "nodemon": "^3.0.1" + "express": "^4.21.2", + "mongoose": "^8.8.4", + "nodemon": "^3.1.7" } -} +} \ No newline at end of file diff --git a/server.js b/server.js index 647e7b14..f7fd824b 100644 --- a/server.js +++ b/server.js @@ -1,32 +1,121 @@ import express from "express"; import cors from "cors"; import mongoose from "mongoose"; +import { Netflix } from "./models/NetflixModel.js"; +import netflixData from "./data/netflix-titles.json"; -// If you're using one of our datasets, uncomment the appropriate import below -// to get started! -// import avocadoSalesData from "./data/avocado-sales.json"; -// import booksData from "./data/books.json"; -// import goldenGlobesData from "./data/golden-globes.json"; -// import netflixData from "./data/netflix-titles.json"; -// import topMusicData from "./data/top-music.json"; - -const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; +const mongoUrl = process.env.MONGO_URL || "mongodb://localhost:27017/project-mongo"; mongoose.connect(mongoUrl); mongoose.Promise = Promise; -// Defines the port the app will run on. Defaults to 8080, but can be overridden -// when starting the server. Example command to overwrite PORT env variable value: -// PORT=9000 npm start const port = process.env.PORT || 8080; const app = express(); -// Add middlewares to enable cors and json body parsing app.use(cors()); app.use(express.json()); -// Start defining your routes here +// Seed the database if RESET_DB is set +if (process.env.RESET_DB) { + const seedDatabase = async () => { + await Netflix.deleteMany({}); + netflixData.forEach(async (item) => { + await new Netflix(item).save(); + }); + }; + seedDatabase(); +} + +// Home route with API documentation app.get("/", (req, res) => { - res.send("Hello Technigo!"); + res.send({ + message: "Welcome to the Marias Netflix API!", + endpoints: [ + { path: "/", method: "GET", description: "API documentation" }, + { path: "/shows", method: "GET", description: "Get all shows" }, + { + path: "/shows/:id", + method: "GET", + description: "Get a single show by ID", + }, + { + path: "/shows/search", + method: "GET", + description: "Search shows by filters (e.g., title, type, country)", + }, + ], + }); +}); + +// Search shows by filters +app.get("/shows/search", async (req, res) => { + const { title, type, country } = req.query; + const query = {}; + + if (title) { + query.title = new RegExp(title, "i"); + } + if (type) { + query.type = type; + } + if (country) { + query.country = country; + } + + try { + const shows = await Netflix.find(query); + res.status(200).json(shows); + } catch (err) { + res.status(500).json({ error: "Failed to fetch shows", details: err.message }); + } +}); + +// Example stats route +app.get("/shows/stats", async (req, res) => { + try { + const count = await Netflix.countDocuments(); + res.status(200).json({ totalShows: count }); + } catch (err) { + res.status(500).json({ error: "Failed to fetch stats", details: err.message }); + } +}); + +// Get all shows with pagination +app.get("/shows", async (req, res) => { + const { page = 1, limit = 10 } = req.query; // Default: page 1, limit 10 + + try { + const shows = await Netflix.find() + .skip((page - 1) * limit) // Skip the results of previous pages + .limit(Number(limit)); // Limit the number of results per page + + const totalShows = await Netflix.countDocuments(); // Count total number of documents + const totalPages = Math.ceil(totalShows / limit); // Calculate total pages + + res.status(200).json({ + totalShows, + totalPages, + currentPage: Number(page), + shows, + }); + } catch (err) { + res.status(500).json({ error: "Failed to fetch shows", details: err.message }); + } +}); + +// Get a single show by ID +app.get("/shows/:id", async (req, res) => { + const { id } = req.params; + + try { + const show = await Netflix.findOne({ show_id: id }); + if (show) { + res.status(200).json(show); + } else { + res.status(404).json({ error: "Show not found" }); + } + } catch (err) { + res.status(500).json({ error: "Failed to fetch the show" }); + } }); // Start the server