Retrieve the GET query string parameters using Express - node.js

I seem to have troubles on getting the query string parameter on my Postman.
First, I wanted to get all of the game types API by using the url of:
localhost:3000/api/gameType/dota2
Here is the code below:
const router = require('express').Router();
const GameTypeRepository = require('../../repository/GameTypeRepository');
router.get('/', async (req, res) => {
try {
const game_types = await GameTypeRepository.findByName(req.query.name);
res.json(game_types);
} catch (error) {
console.log(error);
res.sendStatus(500);
}
});
GameTypeRepository.js
const BaseRepository = require('../../../shared/repository/BaseRepository');
const GameType = require('../models/GameType');
class GameTypeRepository extends BaseRepository {
constructor(model) {
super(model);
}
findByName(name, fields) {
const options = {
where: { name }
};
if (!!fields && fields) {
options.attributes = fields;
}
return this.model.findOne(options);
}
}
module.exports = new GameTypeRepository(GameType);
But when I execute the url to my Postman, I get this log on my terminal that says:
Executing (default): SELECT `id`, `name`, `description` FROM `game_types` AS `game_types` WHERE `game_types`.`id` = 'dota2';
Which should be 'name' = 'dota2'
Any ideas on how to work with this? TYIA.

I have solved this problem by adding /type in my router.get('/type/:name,
router.get('/type/:name', async (req, res) => {
try {
const game_types = await GameTypeRepository.findByName(req.params.name);
res.json(game_types);
} catch (error) {
res.sendStatus(404);
}
});

Related

NodeJS+Express+SQL Server backend application Error : Incorrect Syntax near '83' , Incorrect Syntax near '68' etc

In my application I get the following errors when I'm trying to reach GET, PUT, DELETE routes (tried POSTMAN and VSCode REST Server):
Error 1:
GET by ID : `Incorrect Syntax near '83'.`
Error 2:
GET ALL : `Incorrect Syntax near '83'.`
Error 3:
PUT : `Incorrect syntax near '85'.`
Error 4:
DELETE : `Incorrect syntax near '68'.`
I have googled the error but most of them are related to spacing errors in parameters in the SQL query but I have checked mine and the queries I have are all correct compared to those.
I suspect if this related to any SQL Server related encoding but not sure.
Below are some of my coding as a start to investigate:
eventController.js
'use strict';
const eventData = require('../data/events');
const getEvents = async (req, res, next) => {
try {
const events = await eventData.getEvents();
res.send(events);
}catch (error) {
res.status(400).send(error.message);
}
}
const getEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const oneEvent = await eventData.getById(eventId);
res.send(oneEvent)
} catch (error) {
res.status(400).send(error.message)
}
}
const updateEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const data = req.body;
const updated = await eventData.updateEvent(eventId, data);
res.send(updated);
} catch (error) {
res.status(400).send(error.message)
}
}
const deleteEvent = async (req, res, next) => {
try {
const eventId = req.params.id;
const deletedevent = await eventData.deleteEvent(eventId);
res.send(deletedevent);
} catch (error) {
res.status(400).send(error.message)
}
}
module.exports = {
getEvents,
getEvent,
updateEvent,
deleteEvent
}
eventslist.sql
SELECT [ord_type],
[ord_no],
[line_seq_no],
[lvl_no],
[cmt_type],
[cmt_seq_no],
[cmt],
[CMT_DOC_TYPE],
[EXTRA_1],
[extra_2],
[extra_3],
[extra_4],
[extra_5],
[extra_6],
[extra_7],
[extra_8],
[extra_9],
[extra_10],
[extra_11],
[extra_12],
[extra_13],
[extra_14],
[extra_15],
[FILLER_0001],
[ID],
[is_ext],
[RowVersion]
FROM [100].[dbo].[OELINCMT_SQL]
utils.js
'use strict';
const fs = require('fs-extra');
const {join} = require('path');
const loadSqlQueries = async (folderName) => {
const filePath = join(process.cwd(), 'data', folderName);
const files = await fs.readdir(filePath);
const sqlFiles = await files.filter(f => f.endsWith('.sql'));
const queries = {};
for (const sqlFile of sqlFiles) {
const query = await fs.readFileSync(join(filePath, sqlFile));
queries[sqlFile.replace(".sql", "")] = query
}
return queries;
}
module.exports = {
loadSqlQueries
}
UPDATE : Added data/events
index.js
'use strict';
const utils = require('../utils');
const config = require('../../config');
const sql = require('mssql');
const getEvents = async () => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const list = await pool.request().query(sqlQueries.eventslist);
return list.recordset;
} catch (error) {
return error.message;
}
}
const getById = async (eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const oneEvent = await pool.request()
.input('eventId', sql.Char(8), eventId)
.query(sqlQueries.eventbyId);
return oneEvent.recordset;
} catch (error) {
return error.message;
}
}
const updateEvent = async (eventId, eventData) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const update = await pool.request()
.input('eventId', sql.Char(8), eventId)
.input('cmt', sql.NVarChar(4000), eventData.cmt)
.query(sqlQueries.updateEvent);
return update.recordset;
} catch (error) {
return error.message
}
}
const deleteEvent = async (eventId) => {
try {
let pool = await sql.connect(config.sql);
const sqlQueries = await utils.loadSqlQueries('events');
const deleted = await pool.request()
.input('eventId', sql.Char(8), eventId)
.query(sqlQueries.deleteEvent);
return deleted.recordset;
} catch (error) {
return error.message
}
}
module.exports = {
getEvents,
getById,
updateEvent,
deleteEvent
}
eventbyId.sql
SELECT [ord_type]
,[ord_no]
,[line_seq_no]
,[lvl_no]
,[cmt_type]
,[cmt_seq_no]
,[cmt]
,[CMT_DOC_TYPE]
,[EXTRA_1]
,[extra_2]
,[extra_3]
,[extra_4]
,[extra_5]
,[extra_6]
,[extra_7]
,[extra_8]
,[extra_9]
,[extra_10]
,[extra_11]
,[extra_12]
,[extra_13]
,[extra_14]
,[extra_15]
,[FILLER_0001]
,[ID]
,[is_ext]
,[RowVersion]
FROM [100].[dbo].[OELINCMT_SQL]
WHERE [ord_no] = #eventId
Request for GET ALL via POSTMAN
Request for GET by ID via POSTMAN
Request for GET ALL via REST Server
RAW Body of GET ALL request
RAW Body of GET by ID request

Express: res.send() returns an empty object

I have a setup that uses a MySQL server node and express, I have created an update statement on a SQL file and got it to work with the node via patch request on the postman.
It seems to work and it updates the server, however, when I try to get the recently updated object or even a success message, I get an empty object or nothing, even though the data has been updated.
Can anyone help me get some sort of response on postman?
update.sql
UPDATE [dbo].[RetailerThemes]
SET [Name] = #name,
[PrimaryColourPalette_main] = #primaryColourPalette_main
WHERE [UniqueThemedPageName] = #UniqueThemedPageName
router.js
router.patch("/update", internal, async (req, res) => {
try {
//do the update
const updateRetailer =
await retailerController.updateRetailerConfigByName(req, res)
console.log(`Update Retailer Routes: ${updateRetailer}`)
res.status(200).send(
{updateRetailer}
);
} catch (error) {
console.log(error);
}
});
controller.js
const updateRetailerConfigByName = async (req, res) => {
try {
// Credentials from Request
let retailername = req.retailername;
// Data from Repository
const thisRetailerConfig = await retailerRep.updateRetailerConfigDetails(
retailername
);
console.log( `thisRetailerConfig: ${thisRetailerConfig}`)
} catch (error) {
console.log(error)
}
};
repo.js
async function updateRetailerConfigDetails(retailername) {
try {
//RetailerTheme
const sqlcommanda = await tsql.loadSql(
"tsql",
//"GetRetailerThemeByThemedPageName.sql"
"UpdateRetailer.sql"
);
let pool = await sql.connect(sqlConfig);
const themes = await pool
.request()
.input("name", sql.VarChar(150), "b") // change 80700 to variable
.input("UniqueThemedPageName", sql.VarChar(150), retailername)
.input("primaryColourPalette_main", sql.VarChar(9), "#c00")
.query(sqlcommanda)
;
if (themes.rowsAffected != 1) {
console.log("Retailer not found for ", retailername, sqlcommanda);
return { isFound: false };
}
const theme = themes.recordset[0];
console.log(`The Theme: ${theme}`)
return theme;
} catch (error) {
console.log(error.message);
return {};
}
}
Here is a screenshot of what I get on the postman, the update works but the response is an empty object.

Fetching data from MongoDB and displaying it in React App

I am working on creating a web app of an interactive map of campus for the school I'm attending. The web-app will allow students to click on a specific building on campus, which will bring up a map of the classrooms in that building. From there, a user can then click on a classroom which will then display a list of all classes in that room for each day of the school week. I have created my own database of all the classes offered at my school with attributes such as name, section, building, roomnum, and coursenum. I have done enough of the backend where I can connect to my database using Insonmia/Postman where I am able to filter classes based on building, room number and course section (Accounting, Biology etc.) The problem that I am running into is actually displaying the data from my database on the frontend part of my application.
Here is the backend section of my application so far...
server.js
import express from "express"
import cors from "cors"
import classes from "./api/classes.route.js"
const app = express()
app.use(cors())
app.use(express.json())
app.use("/api/v1/classes", classes)
app.use("*", (req, res) => res.status(404).json({ error: "not found"}))
export default app
index.js
import app from "./server.js"
import mongodb from "mongodb"
import dotenv from "dotenv"
import ClassesDAO from "./dao/ClassesDAO.js"
dotenv.config()
const MongoClient = mongodb.MongoClient
const port = process.env.PORT || 8000
MongoClient.connect(
process.env.UJCLASSES_DB_URI,
{
maxPoolSize: 50,
wtimeoutMS: 2500,
useNewUrlParser: true }
)
.catch(err => {
console.error(err.stack)
process.exit(1)
})
.then(async client => {
await ClassesDAO.injectDB(client)
app.listen(port, () => {
console.log(`listening on port ${port}`)
})
})
classesDAO.js
import mongodb from "mongodb"
const ObjectId = mongodb.ObjectID
let classes
export default class ClassesDAO {
static async injectDB(conn) {
if (classes) {
return
}
try {
classes = await conn.db(process.env.UJCLASSES_NS).collection("Classes")
} catch (e) {
console.error(
`Unable to establish a collection handle in ClassesDAO: ${e}`,
)
}
}
static async getClasses({
filters = null,
page = 0,
classesPerPage = 20,
} = {}) {
let query
if (filters) {
if ("name" in filters) {
query = { $text: { $search: filters["name"] } }
} else if ("section" in filters) {
query = { "section": { $eq: filters["section"] } }
} else if ("course" in filters) {
query = { "course": { $eq: filters["course"] } }
} else if ("room" in filters) {
query = {"room": { $eq: filters["room"] } }
}
}
let cursor
try {
cursor = await classes
.find(query)
} catch (e) {
console.error(`Unable to issue find command, ${e}`)
return { classesList: [], totalNumClasses: 0 }
}
const displayCursor = cursor.limit(classesPerPage).skip(classesPerPage * page)
try {
const classesList = await displayCursor.toArray()
const totalNumClasses = await classes.countDocuments(query)
return { classesList, totalNumClasses }
} catch (e) {
console.error(
`Unable to convert cursor to array or problem counting documents, ${e}`,
)
return { classesList: [], totalNumClasses: 0 }
}
}
static async getSections() {
let sections = []
try {
sections = await classes.distinct("section")
return sections
} catch (e) {
console.error(`Unable to get sections, ${e}`)
return sections
}
}
static async getBuildings() {
let buildings = []
try {
buildings = await classes.distinct("building")
return buildings
} catch (e) {
console.error('Unable to get buildings, ${e}')
return buildings
}
}
static async getRooms() {
let rooms = []
try {
rooms = await classes.distinct("room")
return rooms
} catch (e) {
console.error('Unable to get rooms, ${e}')
return rooms
}
}
}
classes.controller.js
import ClassesDAO from "../dao/ClassesDAO.js"
export default class ClassesController {
static async apiGetClasses(req, res, next) {
const classesPerPage = req.query.classesPerPage ? parseInt(req.query.classesPerPage, 10) : 20
const page = req.query.page ? parseInt(req.query.page, 10) : 0
let filters = {}
if (req.query.section) {
filters.section = req.query.section
} else if (req.query.course) {
filters.course = req.query.course
} else if (req.query.name) {
filters.name = req.query.name
} else if (req.query.building) {
filters.name = req.query.building
} else if (req.query.room) {
filters.room = req.query.room
}
const { classesList, totalNumClasses } = await ClassesDAO.getClasses({
filters,
page,
classesPerPage,
})
let response = {
classes: classesList,
page: page,
filters: filters,
entries_per_page: classesPerPage,
total_results: totalNumClasses,
}
res.json(response)
}
static async apiGetClassSections(req, res, next) {
try {
let section = await ClassesDAO.getSections()
res.json(section)
} catch (e) {
console.log(`api, ${e}`)
res.status(500).json({ error: e })
}
}
static async apiGetClassBuildings(req, res, next) {
try {
let building = await ClassesDAO.getBuildings()
res.json(building)
} catch (e) {
console.log('api, ${e}')
res.status(500).json({ error: e })
}
}
static async apiGetClassRooms(req, res, next) {
try{
let room = await ClassesDAO.getRooms()
res.json(room)
} catch (e) {
console.log('api, ${e}')
res.status(500).json({ error: e })
}
}
}
classes.route.js
import express from "express"
import ClassesCtrl from "./classes.controller.js"
const router = express.Router()
router.route("/").get(ClassesCtrl.apiGetClasses)
router.route("/sections").get(ClassesCtrl.apiGetClassSections)
router.route("/buildings").get(ClassesCtrl.apiGetClassBuildings)
router.route("/rooms").get(ClassesCtrl.apiGetClassRooms)
export default router
I understand that this is not a platform that spits out exact answers, however that is not what I'm looking for. I have been stuck on this problem for over a week and have noticed that my project seems to be different than others. For my project, all I need to do is fetch data from an already completed database and display it. I do not need update, delete or insert functionality.
If anyone could point me in the right direction, or link any docs that could help me out I would be very grateful.

How to dynamically delete MongoDB entry using API route

I would just like to simply delete a record from a dynamically displayed list. I've tried every permutation of the backend code and ai just can't get it to work.
The backend is called like this:
async function deletePost() {
setLoading(true)
try {
await axios.delete(`/api/delete/${id}`)
alert("Post deleted")
}
catch (err) {
// notify user that something went wrong
console.log(err)
}
finally {
setLoading(false)
}
setLoading(false)
}
And /api/delete/${id} looks like this:
import { connectToDatabase } from "util/mongodb"
export default async (req, res) => {
const { id } = req.query;
console.log(id)
try {
const { db } = await connectToDatabase()
await db.collection("users").deleteOne({'_id': `ObjectId("${id}")`})
res.sendStatus(200).send({ done: true })
}
catch (error) {
return res.json({ error })
}
}
The console log shows the correct post id, the alert in the 'try' frontend code displays, but the dam post just wont delete. Can anyone offer any advice please? I have tried ".deleteOne({'_id': id})" but that does nothing either.
I believe you are searching for a string, instead of the ObjectId, so no documents match.
You can fix it by converting to ObjectId and then using the value converted, .deleteOne.
var ObjectId = require('mongodb').ObjectId;
const { id } = req.query;
const convertedObjectId = new ObjectId(id);
db.collection("users").deleteOne({_id: convertedObjectId })
Actual example from documentation:
try {
db.orders.deleteOne( { "_id" : ObjectId("563237a41a4d68582c2509da") } );
} catch (e) {
print(e);
}
Reference: MongoDB Documentation - Delete One.
Fixed problem:
app.delete("/cars/:id", async (req, res) => {
const carsId = req.params.id;
const query = { _id: ObjectId(carsId) };
const result = await carCollection.deleteOne(query);
res.send(result);
});

How to update document by ID without using model

I have Card model and I have an API where I'm looking for a document by ID.
app.post("/api/postcomment", async (req,res) => {
const data = req.body
const reqUrl = req.headers.referer
const re = new RegExp('([a-zA-Z0-9]*$)', 'i')
const fixedUrl = reqUrl.match(re)
try {
await Card.update({_id: fixedUrl}, {$push:{'comments': data}})
const card = await Card.findById(fixedUrl)
return res.json(card)
} catch (err) {
throw err
}
})
It works fine. But now I have few more models. All should work the same way to them. But how can I make this code reusable for every model?
Or maybe there is a way to pass a name of my model to API? and then use it like this:
app.post("/api/postcomment", async (req,res, modelName) => {
const data = req.body
const reqUrl = req.headers.referer
const re = new RegExp('([a-zA-Z0-9]*$)', 'i')
const fixedUrl = reqUrl.match(re)
try {
await modelName.update({_id: fixedUrl}, {$push:{'comments': data}})
const item = await modelName.findById(fixedUrl)
return res.json(item )
} catch (err) {
throw err
}
})
Solution1: You can create two helper functions and call the from the router. Both function accept the model object:
let updateDocument = (model, fixedUrl, data) => {
return model.update({ _id: fixedUrl }, { $push: { comments: data }})
}
let getDocument = (model, fixedUrl) => {
return model.findById(fixedUrl)
}
app.post("/api/postcomment", async (req, res, modelName) => {
const data = req.body
const reqUrl = req.headers.referer
const re = new RegExp('([a-zA-Z0-9]*$)', 'i')
const fixedUrl = reqUrl.match(re)
try {
await updateDocument(Card, fixedUrl, data)
const item = await getDocument(Card, fixedUrl)
return res.json(item )
} catch (err) {
throw err
}
})
Solution2: The much better solution is to create a base class (service), with the common functionality. And extend it for each model:
class BaseService {
constructor(model) {
this.model = model;
}
getDocument(data) {
return this.model.findOne(...);
}
updateDocument(data) {
return this.model.update(...);
}
}
class CardService extends BaseService {
constuctor() {
super(Card);
}
}

Resources