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

Mongo API #504

Open
wants to merge 5 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
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
# Project Mongo API

Replace this readme with your own information about your project.
This project is an Express.js application that provides a RESTful API for interacting with a MongoDB database of books. It allows users to retrieve books by various attributes such as author, title, ISBN, and language. The project also features an optional database reset functionality to seed the database with a predefined set of books.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
## Features
MongoDB integration for storing and querying books data.

## The problem
CORS enabled for cross-origin requests.

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?
RESTful API endpoints to interact with the books database:
Get all books
Get books by author
Get books by title
Get books by ISBN
Get books by language

Database seeding: Optionally populate the database with sample data from a books.json file.

## 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://project-mongo-api-7ch7.onrender.com/
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@
"@babel/node": "^7.16.8",
"@babel/preset-env": "^7.16.11",
"cors": "^2.8.5",
"dotenv": "^16.4.7",
"express": "^4.17.3",
"express-list-endpoints": "^7.1.1",
"mongoose": "^8.0.0",
"nodemon": "^3.0.1"
},
"devDependencies": {
"@types/node": "^22.10.2"
}
}
126 changes: 115 additions & 11 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,136 @@
import express from "express";
import cors from "cors";
import mongoose from "mongoose";
import booksData from "./data/books.json";
import dotenv from "dotenv";

// 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";
dotenv.config()

const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo";
mongoose.connect(mongoUrl);
mongoose.Promise = Promise;
// Connecting to MongoDB
// const mongoUrl = process.env.MONGO_URL || 'mongodb://127.0.0.1:27017/books'

// Connecting to MongoDB Atlas
const mongoURI = process.env.MONGODB_URI


mongoose.connect(mongoURI)

.then(() => {
console.log('MongoDB successfully connected!')
})
.catch((error) => {
console.error('Error to connect with MongoDB', error)
})

// Setting a book schema and model
const Book = mongoose.model('Book', new mongoose.Schema({
title: String,
authors: String,
isbn: Number,
language_code: String,
num_pages: Number
}));

// 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();
const listEndpoints = require("express-list-endpoints")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this not be imported like your other packages? 👀


if (process.env.RESET_DB) {
const seedDatabase = async () => {
await Book.deleteMany({});
booksData.forEach(book => {
new Book(book).save()
})
}
seedDatabase()
}
Comment on lines +41 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK to remove once you've seeded your DB


// Add middlewares to enable cors and json body parsing
app.use(cors());
app.use(express.json());

// Start defining your routes here
app.get("/", (req, res) => {
res.send("Hello Technigo!");
const endpoints = listEndpoints(app)
res.json({
message: "Welcome!",
endpoints: endpoints
});
});

// Route to get books
app.get('/books', async (req, res) => {
try {
const books = await Book.find()
res.json(books)
}catch (error) {
console.error('Error retrieving books', error);
res.status(500).send('Server error');
}
});

// Route to get books by author
app.get('/books/author/:author', async (req, res) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're still returning books and not authors, so it would be more RESTful to put this as a query param under the /books endpoint

const { author } = req.params; // Get the author from the URL parameter
try {
const books = await Book.find({ authors: new RegExp(author, 'i') }); // Find books by author (case insensitive)
if (books.length === 0) {
return res.status(404).send('No books found for this author');
}
res.json(books);
} catch (error) {
console.error('Error retrieving books by author', error);
res.status(500).send('Server error');
}
});

// Route to get books by title / words of title
app.get('/books/title/:title', async (req, res) => {
const { title } = req.params; // Get the title from the URL parameter
try {
const books = await Book.find({
title: {$regex: title, $options: 'i' }})
if (books.length === 0) {
return res.status(404).send('No books found for this author');
}
res.json(books);
} catch (error) {
console.error('Error retrieving book', error);
res.status(500).send('Server error');
}
});

// Route to get books by isbn
app.get('/books/isbn/:isbn', async (req, res) => {
const { isbn } = req.params;
try {
const book = await Book.findOne({ isbn: isbn });
if (!book) {
return res.status(404).send('Book not found');
}
res.json(book);
} catch (error) {
console.error('Error retrieving book by ISBN', error);
res.status(500).send('Server error');
}
});

// Route to get books by language
app.get('/books/language/:language', async (req, res) => {
const { language } = req.params;
try {
const books = await Book.find({ language_code: language });
if (books.length === 0) {
return res.status(404).send('No books found for this language');
}
res.json(books);
} catch (error) {
console.error('Error retrieving books by language', error);
res.status(500).send('Server error');
}
});
Comment on lines +91 to 134
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with these filters


// Start the server
Expand Down