Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

project-mongo-api-ji #495

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
# Project Mongo API

Replace this readme with your own information about your project.
Utilize MongoDB and Mongoose to model a dataset of Netflix titles with RESTful API endpoints and Mongoose queries for efficient data retrieval and manipulation.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
Implement features such as pagination to enhance the functionality of the API.

## 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?
Had to refer to documentation to implement pagination.
I would like to continue working on the frontend.

## View it live
Backend:
https://project-mongo-api-z0mw.onrender.com

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.
Frontend:
https://melodic-gnome-35f6b0.netlify.app/
https://github.com/jyy009/project-mongo-api-frontend

## Endpoints
"/titles" Fetch all Netflix titles. Query by: name, type, cast, country.
"/titles/year/:year" Fetch titles by year.
"/titles/:titleId" Fetch one title by it's id.

## Queries
"name": Filter titles by title name.
"type": Filter titles by type of title, either 'tv' or 'movie'.
"cast": Filter titles by cast.
"country": Filter titles by country.
21 changes: 21 additions & 0 deletions models/Title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import mongoose from "mongoose";

const { Schema } = mongoose;

export const titleSchema = new 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 Title = mongoose.model("Title", titleSchema);
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
"@babel/node": "^7.16.8",
"@babel/preset-env": "^7.16.11",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.17.3",
"mongoose": "^8.0.0",
"nodemon": "^3.0.1"
"express-list-endpoints": "^7.1.0",
"mongodb": "^6.6.1",
"mongoose": "^8.3.4",
"nodemon": "^3.1.0"
}
}
108 changes: 99 additions & 9 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import express from "express";
import expressListEndpoints from "express-list-endpoints";
import cors from "cors";
import mongoose from "mongoose";

// 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";
import { Title } from "./models/Title";
import netflixData from "./data/netflix-titles.json";
require("dotenv").config();

const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo";
mongoose.connect(mongoUrl);
mongoose.Promise = Promise;

// Seed the database
if (process.env.RESET_DB) {
const seedDatabase = async () => {
console.log("Resetting and seeding");
await Title.deleteMany();

netflixData.forEach((item) => {
new Title(item).save();
});
console.log("Seeding completed");
};
seedDatabase();
}

// 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
Expand All @@ -24,9 +34,89 @@ const app = express();
app.use(cors());
app.use(express.json());

const paginateQuery = (req, res, next) => {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 20;

req.pagination = {
page,
limit,
skip: (page - 1) * limit,
};
next();
};

const generateQueryUsage = (endpoint) => {
const queryUsage = {};
if (endpoint.path === "/titles") {
queryUsage.name = "Filter by title name (case-insensitive)";
queryUsage.type =
"Filter by title type, either `tv` or `movie` (case-insensitive)";
queryUsage.cast = "Filter by featured cast (case-insensitive)";
queryUsage.country = "Filter by different countries (case-insensitive)";
}
return queryUsage;
};

// Start defining your routes here
app.get("/", (req, res) => {
res.send("Hello Technigo!");
const endpoints = expressListEndpoints(app).map((endpoint) => ({
path: endpoint.path,
methods: endpoint.methods,
query: generateQueryUsage(endpoint),
}));
res.json(endpoints);
});

// Route for all titles and filters
app.get("/titles", paginateQuery, async (req, res) => {
const { name, type, cast, country } = req.query;
let query = {};

if (name) query.title = { $regex: name, $options: "i" };
if (type) query.type = { $regex: type, $options: "i" };
if (cast) query.cast = { $regex: cast, $options: "i" };
if (country) query.country = { $regex: country, $options: "i" };

const allTitles = await Title.find(query)
.skip(req.pagination.skip)
.limit(req.pagination.limit)
.exec();

if (allTitles.length === 0) {
res.status(404).send("No titles were found");
} else {
res.json(allTitles);
}
});

// Route for one title by ID
app.get("/titles/:titleId", async (req, res) => {
const { titleId } = req.params;

const byId = await Title.findById(titleId).exec();

if (byId) {
res.json(byId);
} else {
res.status(404).send("No title found by that id");
}
});

// Route for titles by year
app.get("/titles/year/:year", paginateQuery, async (req, res) => {
const year = req.params.year;

const byYear = await Title.find({ release_year: year })
.skip(req.pagination.skip)
.limit(req.pagination.limit)
.exec();

if (byYear.length > 0) {
res.json(byYear);
} else {
res.status(404).send("No title found by that year");
}
});

// Start the server
Expand Down