Cannot GET /mentor/mypage/pre-ordered_Lectures/1 - javascript

i'm not really good at English and beginner of coding. i use javascript and my OS is Mac.
Anyway, i wrote row query in MysqlWorkbench and now, i want to write it in VScode to sequelize.
select reservation_datetime
from LectureReservation
Inner Join Lecture
On LectureReservation.lecture_id = Lecture.id
Where Lecture.mentor_id = 1
this is my query and
module.exports = {
get: (req, res) => {
if (req.params.id) {
LectureReservation
.findOne({
include: [
{
model: Lecture,
where: {
Lecture_id: Lecture.id,
},
},
],
attributes: ['reservation_datetime'],
where: {
mentor_id: req.params.id,
},
})
.then((result) => {
if (result) {
res.status(200).json({ message: 'OK!' });
} else {
res.status(409).json({ message: 'Wrong Access' });
}
})
.catch((err) => {
res.status(500).send(err);
});
}
},
};
this is my sequelize code. and
this is my err code in postman..
Result: How can I edit my sequelize code to fix my postman err..?

It seems this is not a sequelize related error. The error code is 404. Which means the route is not available. Please check your routes.
Also you don't need to specify the include condition if your sequelize models associated properly. You can just write
include: [
{
model: Lecture
},
],

Related

Sequelize: Append key value to Javascript collection

Good morning everyone!
I'm developing an application with Node.js and Angular, and I'm getting a little stuck lately.
I need to append a custom key -> value to an existing query result collection.
This is the function I have:
exports.findAll = (req, res) => {
Project.findAll({
include: [{
all: true,
include: [{
all: true
}]
}]
})
.then(data => {
data.forEach(
(project) => {
// <-------- HERE GOES THE APPEND
}
);
res.send(data);
})
.catch(err => {
res.status(500).send({
message: err.message || "Error retrieving projects"
});
});
};
Description:
After getting the result from the model query, I iterate over each result (aka Project).
Then, what I need to do is append a key -> value pair to that very Project.
By now, I'd like to do something like this:
exports.findAll = (req, res) => {
Project.findAll({
include: [{
all: true,
include: [{
all: true
}]
}]
})
.then(data => {
data.forEach(
(project) => {
project.cat = "miaw";
}
);
res.send(data);
})
.catch(err => {
res.status(500).send({
message: err.message || "Error retrieving projects"
});
});
};
This try hasn't made any changes in my JSON collection, and I don't know how to accomplish it neither.
Could someone give me some help?
I've searched everywhere but couldn't find anything useful.
Thank you so much!
You just need to get plain objects from model instances and then you can add whatever you need to:
const projects = data.map(x => x.get({ plain: true }))
projects.forEach(
(project) => {
project.cat = "miaw";
}
);
res.send(projects);

Can't render the page with ejs routing params and mongoose

Ok, I've got an user object:
{
posts: [
{
_id: 603f1c1b966c28291cb61d60,
title: '1111',
content: '1111',
__v: 0
},
{
_id: 603f5479c989d92fbc1d082c,
title: '222',
content: '222',
__v: 0
},
{
_id: 603f5e39ddcda01f281f8931,
title: '3333',
content: '3333',
__v: 0
}
],
_id: 603f1c14966c28291cb61d5f,
username: '1',
mail: '1#1.ru',
__v: 3
}
On the main page with all posts i click "read more" on single post,(button has a value of this post's id, i checked, at this point everything OK) and new page with single complete post should render, with two values: title and content, simple.
Here's what i do in app.js:
app.get("/posts/:postID", function(req, res) {
const postID = req.params.postID;
User.findById(req.user.id, (err, user)=>{
user.posts.find(post=>{
post._id === postID;
console.log(post);
});
});
At this point log return all 3 posts.Why? I've tried different ways, and as i remember, i've got post i needed, but still coudnt render data from it. Post page is:
<div class="block">
<h1><%= title %></h1>
<p><%= content %></p>
</div>
});
And when i tried:
res.render("post",{
title:post.title,
content: post.content
})
that didn't work.But, if i try for example:
res.render("post",{
title:req.user.posts[0].title,
content: req.user.posts[0].content
})
, that works.
Can anyone help me? And remember, User.find - data from mongoDB, req.user - same data, but stored in session when user logged in. I guess it,s not that good to render data from sesion. But, at this point any solution is acceptable, i stacked badly)
There are two approaches that you can take here:
Use an if condition and return only the matching element.
app.get("/posts/:postID", function (req, res) {
const postID = req.params.postID;
User.findById(req.user.id, (err, user) => {
user.posts.find(post => {
if (post._id === postID) {
console.log(post);
}
});
});
Return only the desired element directly from the query.
Excuse me for taking the liberty and modifying the code a bit.
const ObjectId = mongoose.Types.ObjectId; // Hoping you are using mongoose.
app.get("/posts/:postID", async function (req, res) {
try {
const postID = req.params.postID;
let post = await User.aggregate([
{
$match: {
"_id": ObjectId(req.user.id)
}
},
{
$unwind: "$posts"
},
{
$match: {
"posts._id": ObjectId(postID)
}
}
]);
if (post && post.length > 0) {
console.log(post[0])
return post; // or anyhow you want to format and return
}
} catch (exception) {
// Handle how you want.
}
});

How to check if there are no more documents to update using findOneAndUpdate

So I am learning CRUD for a school project and I followed a tutorial that was really useful. However, when I completed it I noticed that when there are no more quotes to update, it still updates quotes. How can I change this so that it will stop updating quotes that arent even there?
app.put('/quotes', (req, res) => {
quoteCollection.findOneAndUpdate(
{ name: 'Yoda' },
{
$set: {
name: req.body.name,
quote: req.body.quote
}
},
{upsert: true}
)
.then(result => {
//The if block that i am trying
if (result.deletedCount === 0) {
return res.json('No quote to delete')
}
})
.catch(error => console.error(error))
})
Why are you passing {name: "Yoda}? This route is supposed to only update the quote with "Yoda" as its name? If not, then you need to grab from the request object the quote that should be updated.
I tried to create a different version, based on the assumption that the quote that should be updated will come from the req.body:
app.put("/quotes", async (req, res) => {
//Grab the name/id/identifier for the quote you want to update from the body
const query = req.body.name;
// Try to update the document on the database
try {
const result = await quoteCollection.findOneAndUpdate(
query,
{
name: req.body.name,
quote: req.body.quote,
},
{
upsert: true,
new: true,
}
);
// If it worked, it will return the updated quote
res.status(200).json({
status: 200,
data: {
result,
},
});
} catch (err) {
res.status(400).json({
status: 400,
message: "Something went wrong",
});
}
});

Axios giving 404 error after delete action

I am running a React app which has a few methods to update user data. One of these features is to delete movies from a favorites movies list using Axios axios.delete:
removeFavorite(event, favorite) {
event.preventDefault();
console.log(favorite);
axios.delete(`https://flix-app-test.herokuapp.com/users/${localStorage.getItem('user')}/favorites/${favorite}`, {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
})
.then(response => {
this.getUser(localStorage.getItem('token'));
})
.catch(err => {
console.log(err);
});
}
This is the code living in index.js file:
app.delete('/users/:username/movies/:movieId', passport.authenticate('jwt', { session: false }), function(req, res) {
Users.findOneAndUpdate({ username : req.params.username }, {
$pull : { favorites : req.params.movieId }
},
{ new : true }, // This line makes sure that the updated document is returned
function(err, updatedUser) {
if (err) {
console.error(err);
res.status(502).send("Error: " + err);
} else {
res.json(updatedUser)
}
});
});
For some reason, I am getting a 404 error message when I try to delete a movie:
Error: "Request failed with status code 404" createError
createError.js:16 settle settle.js:17 handleLoad xhr.js:59
dispatchXhrRequest xhr.js:34 xhrAdapter xhr.js:11 dispatchRequest
dispatchRequest.js:59 promise callback*request Axios.js:53 method
Axios.js:68 wrap bind.js:9 getUser main-view.jsx:58 componentDidMount
main-view.jsx:89 React 6 unstable_runWithPriority
scheduler.development.js:818 React 10 parcelRequire<["index.jsx"]<
index.jsx:21 newRequire src.78399e21.js:47 parcelRequire
src.78399e21.js:81 src.78399e21.js:120
I am unable to find out from where the error comes from, once the authorization is fine, the correct movie is picked up as a response and the messages are shown on console accordingly.
Could any of the colleagues here to help me to find where the error lies? Thanks in advance.
PS: #SuleymanSah provided the solution for the 404 error below, BUT I am adding my own solution as well - to the axios.delete action not working. Check below.
The url in your delete does not match the url in the express app.
You should change favorites to movies to resolve the 404 error.
And to be able to delete the favorite, you should update your code using $in.
app.delete('/users/:username/movies/:movieId', passport.authenticate('jwt', { session: false }), function(req, res) {
Users.findOneAndUpdate({ username : req.params.username }, {
$pull : { favorites : { $in: req.params.movieId } }
},
{ new : true },
function(err, updatedUser) {
if (err) {
console.error(err);
res.status(502).send("Error: " + err);
} else {
res.json(updatedUser)
}
});
});
Depending one how you store the favorites, you may need to pull like this:
$pull: {
favorites: {
_id: { $in: req.params.movieId }
}
}
#SuleymanSah has gracefully provided the solution for the 404 error, but for me, the core problem - the axios.delete not removing entries from the list array, remained.
It turned out that axios.delete only could delete entries made by the app using axios.post. Entries created straight on mongoDB array could not be deleted using axios. So, if you are having a hard time deleting entries, try creating a feature to add them first and deleting them after. In my case, only app-created entries could be app-deleted.

How to handle error and send response in GraphQL

I was starting with GraphQL and I was unable to comprehend how we can throw errors in GraphQL
I went through a couple of articles on the web but almost all of them use Apollo and the code-structure looks very different than how I work.
Consider this piece of code, here where I am making a mutation, now how can send a response message with error and change headers status message in case of error?
AddNewPersonalInfo: {
type: userDashboardType,
args: {
parameter: {
type: userCreationlInputType
}
},
resolve: async (parent, args, context) => {
args.parameter.userId = context.req.headers.userId
//Check if user info already exsist
const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
if (checkIfUserInformationExsist[0]) {
const error = {
code: 403,
message: 'User info Already exsist'
}
throw new Error(error)
} else {
try {
const addLinkedinUser = await insertIntheTable('personal', payload)
return true
} catch (err) {
console.error(err)
throw new Error(err)
}
}
}
}
What I have faced in one of my projects, it is hard to set the status code of the response. So, I made some custom error response to identify correct statusCode using express-graphql
Below is the example (What I have used in one of my projects):
--------app.js file--------
const graphqlHTTP = require('express-graphql')
app.use('/graphql', (req, res) => {
graphqlHTTP({
schema: GraphQLSchema, //A GraphQLSchema instance from GraphQL.js. A schema must be provided.
graphiql: true,
context: { req },
formatError: (err) => {
const error = getErrorCode(err.message)
return ({ message: error.message, statusCode: error.statusCode })
}
})(req, res)
})
--------getErrorCode function implementation--------
const { errorType } = require('../constants')
const getErrorCode = errorName => {
return errorType[errorName]
}
module.exports = getErrorCode
--------Constant.js file--------
exports.errorName = {
USER_ALREADY_EXISTS: 'USER_ALREADY_EXISTS',
SERVER_ERROR: 'SERVER_ERROR'
}
exports.errorType = {
USER_ALREADY_EXISTS: {
message: 'User is already exists.',
statusCode: 403
},
SERVER_ERROR: {
message: 'Server error.',
statusCode: 500
}
}
Now, we are ready to use our setup.
From your query or mutation, you need to require constant file and return custom error:
const { errorName } = require('../constant')
AddNewPersonalInfo: {
type: userDashboardType,
args: {
parameter: {
type: userCreationlInputType
}
},
resolve: async (parent, args, context) => {
args.parameter.userId = context.req.headers.userId
//Check if user info already exsist
const checkIfUserInformationExsist = await getSelectedThingFromTable('CatsWork_personal', 'userId', `${userId}`)
if (checkIfUserInformationExsist[0]) {
const error = {
code: 403,
message: 'User info Already exsist'
}
throw new Error(errorName.USER_ALREADY_EXISTS) // Here you can use error from constatnt file
} else {
try {
const addLinkedinUser = await insertIntheTable('personal', payload)
return true
} catch (err) {
console.error(err)
throw new Error(errorName.SERVER_ERROR) // Here you can use error from constatnt file
}
}
}
}
--------Error response--------
{
error: [{
"statusCode": 403,
"message": "User is already exists."
}],
data: null
}
We just need to write custom error handling from FS side too.
Note:- formatError: is deprecated and replaced by customFormatErrorFn. It will be removed in version 1.0.0. You can refer customFormatErrorFn.
graphql should be an application level layer that shouldn't (see last paragraph why shouldn't and not doesn't) require http to work. Although in 99% of cases it runs on top of http, because of how convenient it is to do so, graphql is itself a layer 7 protocol.
What does that mean in your case? Well, it means you should not mix concepts from HTTP/REST with concepts from graphql and focus on the latter. The headers error code is a HTTP/REST concept, graphql sends errors in the errors field of the response and the nodejs implementation already catches all your errors and adds them to the list. The HTTP status will be always 200, and your clients shouldn't care and consume your graphql api and not a mix of REST with graphql.
That being said, there are couple of things that REST over HTTP does better. So people, including the developers of Apollo, kinda mixed concepts too, mainly because the graphql standard is not complete (aka, it doesn't have a standard/rule for solving all the problems you might encounter while building an API), so people improvised. I wouldn't recommend graphql yet for any serious project.
Reference
You can specify an error function inside graphqlHTTP like this:
app.use("/graphql", graphqlHTTP({
schema,
graphiql: true,
customFormatErrorFn: err => {
try {
err.details = JSON.parse(err.message);
err.message = Array.isArray(err.details.error) ? err.details.error.join(",") : err.details.error;
return err;
} catch {
return err;
}
}
}));
where err.message might contain a JSON object or a string.
you can use those function to generate specific client and server error functions:
const clientError = error => new Error(JSON.stringify({
success: false,
code: 400,
error
}));
const serverError = ({ name, message, stack }) => new Error(JSON.stringify({
success: false,
error: "Server Error",
code: 500,
name,
message,
stack
}));
const userValidationError = err => {
if (err.name === "ValidationError") return clientError(Object.values(err.errors).map(({ message }) => message));
return serverError(err);
}
module.exports = {
clientError,
serverError,
userValidationError
};
userValidationError function is useful if you have a mongodb validation error.
so that you would use it inside resolve function like this:
try {
const createdDocument = await MongooseDoc.create(data);
return createdDocument;
} catch (err) {
throw userValidationError(err);
}
the response would be
{
"errors": [
{
"message": "error details 1,error details 2",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"document"
],
"details": {
"success": false,
"code": 400,
"error": [
"error details 1",
"error details 2"
]
}
}
],
"data": {
"document": null
}
}
if you want to throw a clientError you throw it outside try catch.
Hopefully this code helps someone send dynamic error messages in graphql.

Categories