Sequelize, multer, nodejs - node.js

I currently have a model that includes the following:
title: {
type: Sequelize.STRING
}, name: {
type: Sequelize.STRING
}, images: {
type: Sequelize.STRING
}
I'm storing the file name of the images as a string on POSTGRES by using
//POST METHOD
app.post("/", (req, res) => {
MODEL.create({
images: JSON.stringify(req.files.map(file => file.filename))
})
})
when i try it without the JSON.stringify, i get an error saying images cannot be an array or object (problem 1)
My 2nd problem is now when I try to access the image in my get request I want to change the image from being a filename to a URL and thumbnail URL as below
url: ${baseUrl}${image}_full.jpg
thumbnailUrl: ${baseUrl}${image}_thumb.jpg

Related

Node.js: Cast to ObjectId failed for value "new" (type string)

I am rather new to node and am having an issue that is a bit difficult for me to decipher. I am trying to make a reddit clone. The part that I am working on right now is to allow users to view posts other users have posted. I was trying to implement a new route by pasting in this bit of code
app.get('/', (req, res) => {
Post.find({}).lean()
.then((posts) => res.render('posts-index', { posts }))
.catch((err) => {
console.log(err.message);
})
})
However, I am getting this error when I run it:
Cast to ObjectId failed for value "new" (type string) at path "_id" for model "Post"
It seems like something is wrong with my post.js model, but I can't identify it. Could someone review this and help me identify the triggering factor?
const { Schema, model } = require('mongoose');
const postSchema = new Schema({
title: { type: String, required: true },
url: { type: String, required: true },
summary: { type: String, required: true },
}, { timestamps: true });
module.exports = model('Post', postSchema);

_doc in request body

I am trying to send an object created by MongoDB model as a body of post request in a jest test.
Here is the test:
test("post request successfully creates a new blog", async () => {
const newBlog = new Blog({
title: "My mundane day at home 3",
author: "AbG",
url: "https://www.google.co.in/",
likes: 11,
});
await api
.post("/api/blogs")
.send(newBlog)
.expect(201)
.expect("Content-Type", /application\/json/)
.catch((err) => console.log(err));
const blogs = await Blog.find({});
expect(blogs).toHaveLength(initialBlogs.length + 1);
});
As you can see, I am sending the newBlog as a body of request. But when I receive it in controller, the newBlog is present in the request.body._doc instead of request.body.
I think this has something to do with the mongoose model of blog.
const blogSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
author: {
type: String,
required: true,
},
url: {
type: String,
required: true,
},
likes: {
type: Number,
required: false,
default: 0,
},
});
module.exports = mongoose.model("Blog", blogSchema);
I cannot understand why this is happening.
I found out where I was going wrong.
In the test case, I was creating a mongodb schema instance and passing it as body of request instead of a plain JS object. And in the express app, I was trying to access the request body as a JS object. So that created a confusion.
The changes that I did:
In test:
Instead of
const newBlog = new Blog({....})
I did
const newBlog = {....}
So, I avoided passing mongodb object as request body and created the mongodb object using the constructor immediately before where I needed it.
Here is the post route:
blogsRouter.post("/", async (request, response) => {
const blog = new Blog(request.body);
const savedBlog = await blog.save();
response.status(201).json(savedBlog);
});

Having trouble posting to Mongo DB after external API Call

I'm attempting to make a fetch call to News API and populate my Articles collection in Mongo DB with the data I fetch. I have two files: articles.js, and article.js. - my schema looks like the following:
// Article.js
const ArticleSchema = new Schema({
title: {
type: String,
required: true
},
author: {
type: String,
required: true
},
description: {
type: String,
required: true
},
url: {
type: String,
required: true
},
datePublished: {
type: String,
required: true
},
source: {
type: String,
required: true
}
})
In articles.js, this is what my route looks like. My logic is that I make my fetch call, wait for the JSON to return, then iterate thru that json and map all the information I need to new story objects. Once I have those objects - I want to create a new instance of an Article for each, then post them to my Articles collection in Mongo DB.
/ #route POST /articles -> adds new instance of an article to the database
router.post('/', async (req, res) => {
try {
const res = await fetch('https://newsapi.org/v2/top-headlines?country=us&category=entertainment&apiKey=63c967f7cbd84c11b263b4e4758f1693');
const data = await res.json();
data.articles.forEach(article => {
const storyData = {
title: article.title,
author: article.author,
description: article.description,
url: article.url,
datePublished: article.publishedAt,
source: article.source.name
}
// console.log(storyData)
new Article(storyData)
.save()
})
} catch (err) {
console.error(err.message)
res.status(400).json({ message: err.message })
}
})
After my forEach loop, I get the objects like so:
{
title: `'Matrix 4' Style "Shifted" From Original Trilogy, Says Neil Patrick Harris - Hollywood Reporter`,
author: 'Ryan Parker',
description: 'The actor, who appears in the fourth installment, called the upcoming film "ambitious."',
url: 'https://www.hollywoodreporter.com/heat-vision/matrix-4-style-shifted-from-original-trilogy-says-neil-patrick-harris',
datePublished: '2020-09-16T17:54:26Z',
source: 'Hollywood Reporter'
}
I'm able to get the objects I'd like with the data I need, however when I attempt to call .save(), I receive validation error similar to the following:
"ValidationError: article validation failed: author: Path author is required."
I'm thinking that it may have to do with the fact that when I make post to the DB, the request should list something along the lines of "title: req.body.title", etc... Any thoughts on what could be causing this? My goal is to simply post these to the DB as I create them. Thanks!!!

How to upload image to mongodb using node.js, express.js

Am trying to upload image to the task collection in my mongodb but keep getting an error message.
here is my task model
const mongoose = require('mongoose')
const taskSchema = new mongoose.Schema({
description: {
type: String,
trim: true,
required: true
},
completed: {
type: Boolean,
default: false
},
owner: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
avatar: {
type: Buffer
}
},
{
timestamps: true
})
const Tasks = mongoose.model('Tasks', taskSchema )
module.exports = Tasks
Here is my task router code
router.post('/tasks/me/avatar', auth, upload.single('avatar'), async (req, res) => {
const buffer = await sharp(req.file.buffer).resize({ width: 250, height: 250 }).png().toBuffer()
req.tasks.avatar = buffer
await req.tasks.save()
res.send()
}, (error, req, res, next) => {
res.status(400).send({ error: error.message })
})
error message
[![enter image description here][1]][1]
It keeps giving me an error message of cannot set property 'avatar' of undefined, meanwhile the avatar field has already been defined in the task model.
How can I fix this issue, thanks.
Ok after looking at your answer i'll propose this solution.
Instead of:
req.tasks.avatar = buffer
await req.tasks.save()
Try this
const query = {id: docId}; //prepare a query to find the doc
Task.findOneAndUpdate(query, { $set: {avatar: buffer} }, ()=>{
/Your callback function to run after completed
});
//Then call findOneAndUpdate method from any mongoose.model
//Which will do exactly what its name says:
//Finding ONE element, the first one matching your query
//And then update any values inside $set
//And after that you may use any callback function
Let me know if that helps you out.

object parsing using req parameter and save in mongoose schema

I have a nested object which I am able to fetch properly but unable to store the the nested object values in the schema. Below are my code snippets:
header.js Router File
router.post('',(req, res)=>{
//console.log(req.body)
const header = new headerModel({
register:{
name: req.body.name,
url: req.body.url
},
logo:{
image: req.body.image,
altText: req.body.altText,
url: req.body.url
}
})
console.log(header)
})
module.exports = router
Header.js Schema File
const mongoose = require('mongoose')
const headerSchema = mongoose.Schema({
register: {
name: {
type: String
},
url: {
type: String
}
},
logo: {
image: {
type: String,
},
altText: {
type: String
},
url: {
type: String
},
}
})
module.exports = mongoose.model('header', headerSchema)
JSON
{
"register":{
"name":"Register",
"url":"/register"
},
"logo":{
"image":"/imagePath/ab.png",
"alttext":"Home",
"url":"/"
}
}
I need to store the value of name and url in register and signin objects respectively in Router File
the header in Router File when logged on console doesn't include register or logo
Because you get the data from JSON in the wrong way and you haven't saved the header yet. You can solve it by:
let header = new headerModel({
register:{
name: req.body.register.name,
url: req.body.register.url
},
logo:{
image: req.body.logo.image,
altText: req.body.logo.altText,
url: req.body.logo.url
}
})
header.save(function (err, doc) {
// Do some thing you want
})
Related information can be found here.

Resources