why an empty array when I do an app.get()? - mongodb

So I have a mongodb database to which I have imported some json data to its collection.
When I do a db.posts.find(), the data imported successfully, but when I attempt a get request, I get an empty array [].
Here is my server.js file:
'use strict';
const express = require('express');
const morgan = require('morgan');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const { DATABASE_URL, PORT } = require('./config');
const { BlogPost } = require('./models');
const app = express();
app.use(morgan('common'));
app.use(express.json());
app.get('/posts', (req, res) => {
BlogPost
.find()
.then(posts => {
res.json(posts.map(post => post.serialize()));
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'something went terribly wrong' });
});
});
app.get('/posts/:id', (req, res) => {
BlogPost
.findById(req.params.id)
.then(post => res.json(post.serialize()))
.catch(err => {
console.error(err);
res.status(500).json({ error: 'something went horribly awry' });
});
});
app.post('/posts', (req, res) => {
const requiredFields = ['title', 'content', 'author'];
for (let i = 0; i < requiredFields.length; i++) {
const field = requiredFields[i];
if (!(field in req.body)) {
const message = `Missing \`${field}\` in request body`;
console.error(message);
return res.status(400).send(message);
}
}
BlogPost
.create({
title: req.body.title,
content: req.body.content,
author: req.body.author
})
.then(blogPost => res.status(201).json(blogPost.serialize()))
.catch(err => {
console.error(err);
res.status(500).json({ error: 'Something went wrong' });
});
});
app.delete('/posts/:id', (req, res) => {
BlogPost
.findByIdAndRemove(req.params.id)
.then(() => {
res.status(204).json({ message: 'success' });
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'something went terribly wrong' });
});
});
app.put('/posts/:id', (req, res) => {
if (!(req.params.id && req.body.id && req.params.id === req.body.id)) {
res.status(400).json({
error: 'Request path id and request body id values must match'
});
}
const updated = {};
const updateableFields = ['title', 'content', 'author'];
updateableFields.forEach(field => {
if (field in req.body) {
updated[field] = req.body[field];
}
});
BlogPost
.findByIdAndUpdate(req.params.id, { $set: updated }, { new: true })
.then(updatedPost => res.status(204).end())
.catch(err => res.status(500).json({ message: 'Something went wrong' }));
});
app.delete('/:id', (req, res) => {
BlogPost
.findByIdAndRemove(req.params.id)
.then(() => {
console.log(`Deleted blog post with id \`${req.params.id}\``);
res.status(204).end();
});
});
app.use('*', function (req, res) {
res.status(404).json({ message: 'Yo stupido, Not Found' });
});
// closeServer needs access to a server object, but that only
// gets created when `runServer` runs, so we declare `server` here
// and then assign a value to it in run
let server;
// this function connects to our database, then starts the server
function runServer(databaseUrl, port = PORT) {
return new Promise((resolve, reject) => {
mongoose.connect(databaseUrl, err => {
if (err) {
return reject(err);
}
server = app.listen(port, () => {
console.log(`Your app is listening on port ${port}`);
resolve();
})
.on('error', err => {
mongoose.disconnect();
reject(err);
});
});
});
}
// this function closes the server, and returns a promise. we'll
// use it in our integration tests later.
function closeServer() {
return mongoose.disconnect().then(() => {
return new Promise((resolve, reject) => {
console.log('Closing server');
server.close(err => {
if (err) {
return reject(err);
}
resolve();
});
});
});
}
// if server.js is called directly (aka, with `node server.js`), this block
// runs. but we also export the runServer command so other code (for instance, test code) can start the server as needed.
if (require.main === module) {
runServer(DATABASE_URL).catch(err => console.error(err));
}
module.exports = { runServer, app, closeServer };
and here is my config.js file:
'use strict';
exports.DATABASE_URL =
process.env.DATABASE_URL || 'mongodb://localhost/seed_data';
exports.PORT = process.env.PORT || 8080;
In my models.js file, this is what my mongoose model looks like:
'use strict';
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const blogPostSchema = mongoose.Schema({
author: {
firstName: String,
lastName: String
},
title: {type: String, required: true},
content: {type: String},
created: {type: Date, default: Date.now}
});
blogPostSchema.virtual('authorName').get(function() {
return `${this.author.firstName} ${this.author.lastName}`.trim();
});
blogPostSchema.methods.serialize = function() {
return {
id: this._id,
author: this.authorName,
content: this.content,
title: this.title,
created: this.created
};
};
const BlogPost = mongoose.model('BlogPost', blogPostSchema);
module.exports = {BlogPost};

The issue is with your first parameter in your mongoose.model(). Since you shared that the collection name is posts, that should be the name of your first parameter as a string 'posts'.
Checkout this documentation on how to declare collection name and model name:
How to declare collection name and model name in mongoose
So your mongoose.model() should look like this:
const BlogPost = mongoose.model('posts', blogPostSchema);
Give that a try.

Related

Mongoose pre save middleware is not triggering/saving hashed passwords to db

I am trying to pre save and hash password with bcrypt in mongoose in my next.js project, but password still unhashed. i tryed every link in stackoverflow and didnt solve it, the password still saved unHashed.
mongoose version: 6.9.1
this is my users.model file:
import {
models,
model,
Schema,
} from 'mongoose';
import bcrypt from 'bcrypt';
const UserSchema: Schema = new Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
displayName: {
type: String,
required: true,
},
role: {
type: String,
},
});
UserSchema.pre('save', function (next) {
console.log('Pre-Save Hash has fired.');
let user = this;
bcrypt.genSalt(10, (err, salt) => {
if (err) console.error(err);
bcrypt.hash(user.password, salt, (err, hash) => {
user.password = hash;
next();
});
});
});
const UserModel = models.Users || model('Users', UserSchema, 'users');
export default UserModel;
this is my adding function file:
import dbConnect from '#/utils/mongodb';
import UserModel from '#/models/user.model';
import { NextApiRequest, NextApiResponse } from 'next';
import { MongoError } from 'mongodb';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// const { email, password } = req.query;
try {
dbConnect();
const query = req.body;
const newUser = new UserModel(query);
const addedUser= await newUser.save(function (err: MongoError) {
if (err) {
throw err;
}
});
res.status(200).json(addedUser);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Internal server error' });
}
}
i cant see the 'Pre-Save Hash has fired.' in my console also..
// You need to add user.isModified("password")
userSchema.pre("save", function (next) {
var user = this;
if (user.isModified("password")) {
bcrypt.genSalt(SALT_I, (err, salt) => {
if (err) {
return next(err);
}
bcrypt.hash(user.password, salt, (err, hash) => {
if (err) {
return next(err);
}
user.password = hash;
next();
});
});
} else {
next();
}
});
userSchema.methods.comparePassword = function (candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, (err, isMatch) => {
if (err) return cb(err);
cb(null, isMatch);
});
};
// to make register end point
import mongoose from "mongoose";
import User from "../../../models/User";
const dbConnect = async () => {
mongoose
.connect("mongodb://localhost:27017/test")
.then(() => {
console.log("Connected to mongoDb");
})
.catch((error) => {
console.log(error);
});
};
export default async function handler(req, res) {
try {
await dbConnect();
const query = req.body;
const newUser = new User(query);
await newUser.save(function (err, result) {
if (err) {
throw err;
} else {
res.status(200).json(result);
}
});
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal server error" });
}
}
thanks to all.
The problem was in my dbconnect file!

Is there an easier way to post an element in the html-post method?

const express = require("express");
const cors = require("cors");
const dotenv = require("dotenv");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
dotenv.config();
app.use(cors());
app.use(bodyParser.json());
const { Schema } = mongoose;
const userSchema = Schema({
imageUrl: { type: String },
description: { type: String },
title: { type: String },
price: { type: Number },
});
const Users = mongoose.model("users", userSchema);
app.get("/", (req, res) => {
res.send("started");
});
`get metod`
app.get("/users", (req, res) => {
Users.find({}, (err, docs) => {
if (!err) {
res.send(docs);
} else {
res.status(404).json({ message: err });
}
});
});
app.get("/users/:id", (req, res) => {
const { id } = req.params;
Users.findById(id, (err, doc) => {
if (!err) {
if (doc) {
res.send(doc);
}
} else {
res.status(404).json({ message: err });
}
});
});
`delete metod`
app.delete("/users/:id", (req, res) => {
const { id } = req.params;
Users.findByIdAndDelete(id, (err, doc) => {
if (!err) {
res.send("Succesfully deleted");
} else {
res.status(404).json({ message: err });
}
});
});
`post metod`
app.post("/users", (req, res) => {
const obj = {
imageUrl: req.body.imageUrl,
description: req.body.description,
title: req.body.title,
price: req.body.price,
};
console.log(obj);
let user = new Users(obj);
user.save();
res.send({ message: " Succesfully added" });
});
const PORT = process.env.PORT;
const url = process.env.URL.replace("<password>", process.env.PASSWORD);
mongoose.set("strictQuery", true);
mongoose.connect(url, (err) => {
if (!err) {
console.log("DB connected");
app.listen(PORT, () => {
console.log("Server start");
});
}
});
I'm trying to learn how exactly get post delete queries work
I'm trying to reduce the code here, but no matter what I do, small errors appear in the end. I have a json string, I want to pass it to POST method. But the 'execute', and 'executeMethod ' are throwing error as below:
"The method execute(HttpUriRequest) in the type HttpClient is not applicable for the arguments (PostMethod)". i have included the depencencies.

How to create new item in collection if not exists, otherwise, update price and quantity when added to cart

Hi iam new to Vue and trying too build a MEVN application. What iam trying to do is when user adds item in cart it should store one document in mongoDB and if user adds more of same item only the price and quantity for the document should increase and not create new document.
Here is code for client when user adds item in cart,iam using Vue3:
async addToCart(state, product) {
console.log(state);
let dbProducts = await axios
.get(`http://localhost:1337/items/`)
.then((res) => res.data)
.catch((error) => console.log(error));
let item = dbProducts.find((i) => i.id === product.id);
console.log(item);
console.log('addTOcart');
if (item) {
console.log('put request');
item.quantity++;
console.log('quantity', item.quantity);
axios
//.put(`http://localhost:1337/items/${uniqueId}`, item)
.put(`http://localhost:1337/items/`, item)
.then((res) => {
console.log(res.data);
alert(res.data);
})
.catch((error) => console.log(error));
} else {
product = { ...product, quantity: 1 };
state.cart.push(product);
axios.post('http://localhost:1337/items', {
id: product.id,
title: product.title,
price: product.price,
quantity: product.quantity,
shortDesc: product.shortDesc,
category: product.category,
longDesc: product.longDesc,
imgFile: product.imgFile,
serial: product.serial,
});
}
},
And here is code for the server, iam using express js:
const express = require('express');
const app = express();
const Items = require('./Items');
const connection = require('./connection');
const Port = process.env.Port || 1337;
const cors = require('cors');
app.use(cors());
connection();
app.use(express.json());
app.post('/items', (req, res) => {
const data = new Items(req.body);
data
.save()
.then((Items) => {
console.log('item saved', Items);
res.json({ succcess: true, Items });
})
.catch((err) => {
console.log(err);
});
});
app.get('/items', async (req, res) => {
Items.find({}, (err, items) => {
res.json(items);
});
});
app.put('/items', function (req, res) {
console.log(req.body);
//Items.updateOne({ _id: req.body._id }, req.body);
Items.findOneAndUpdate({ _id: req.body._id }, req.body);
// Items.findOne({ _id: req.body._id });
});
app.listen(Port, () => {
console.log(`App running on port ${Port}`);
});
As #HeikoTheißen suggested, you should handle the logic of the operation on the server, using a single POST request:
const express = require('express');
const app = express();
const Items = require('./Items');
const connection = require('./connection');
const Port = process.env.Port || 1337;
const cors = require('cors');
app.use(cors());
connection();
app.use(express.json());
app.post('/items', async (req, res) => {
try {
let item = await Items.findById(req.body.id);
if (!item) {
item = await Items.create(req.body);
} else {
item.quantity++;
await item.save();
}
res.json({ succcess: true, item });
} catch (err) {
res.json({ succcess: false });
}
});
app.listen(Port, () => {
console.log(`App running on port ${Port}`);
});
You should simplify your client code as:
async function addToCart(state, product) {
try {
const { data } = await axios.post('http://localhost:1337/items', product);
// Add new product to card if necessary
if (!state.cart.some((p) => p.id === data.item.id)) {
state.cart.push(data.item);
}
} catch (err) {
console.log(err);
}
}

How to resize and add images in mongo DB with mongoose in node js from client side and also be able to view the images in ejs

I want to resize the image and upload it to Mongo DB is it possible to do it in node and express with mongoose and please add an explanation of the code too. It would be very helpful😀
finally did with multer, gridfs and jimp(main packages)
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const mongoose = require('mongoose');
const multer = require('multer');
const GridFsStorage = require('multer-gridfs-storage');
const Grid = require('gridfs-stream');
const methodOverride = require('method-override');
const crypto = require("crypto")
const Jimp = require("jimp")
const app = express();
// Middleware
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride('_method'));
app.set('view engine', 'ejs');
app.use(express.static("public"));
// Mongo URI
const mongoURI = 'mongodb://localhost:27017/newDB';
// Create mongo connection
//useUnifiedTopology will not work with mongoose.createConnection
const conn = mongoose.createConnection(mongoURI , { useUnifiedTopology: true ,useNewUrlParser: true });
// Init gfs
let gfs;
conn.once('open', () => {
// Init stream
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('uploads');
});
mongoose.connect("mongodb://localhost:27017/newDB", { useUnifiedTopology: true, useNewUrlParser: true })
const imageSchema = new mongoose.Schema({
image: String,
User: String,
forTest: String
});
const Image = mongoose.model('image', imageSchema);
// Create storage engine
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: 'uploads'
};
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage });
app.get('/', (req, res) => {
Image.find({}, function(err, files) {
// Check if files
if (!files || files.length === 0) {
res.render('index', { fileSent: false });
} else {
res.render('index', { fileSent: files });
}
});
});
app.post('/upload', upload.single("file"), (req, res) => {
if(req.file === undefined || req.file === 0 || req.file === ""){
res.redirect("/");
}
if(req.file.contentType === "image/png" || req.file.contentType === "image/jpg" || req.file.contentType === "image/jpeg"){
Jimp.read("http://localhost:3000/image/" + req.file.filename, (err, image) => {
if (err) {
// on every error render the error page with error message and type
console.log(err);
}
image
.resize(550, Jimp.AUTO)
image.getBase64(Jimp.AUTO, (error1, base64Image) => {
if(error1){
console.log(error1);
}
const image1 = new Image({
image: base64Image,
User: "Avichal",
forTest: "Hindi1"
})
image1.save(function(error){
if(error){
console.log(error);
}
})
})
gfs.remove({ _id: req.file.id, root: 'uploads' }, (err, gridStore) => {
if (err) {
console.log(err);
}
res.redirect('/');
});
})
}else{
gfs.remove({ _id: req.file.id, root: 'uploads' }, (err, gridStore) => {
if (err) {
console.log(err);
}
res.redirect('/');
});
}
});
app.get('/:filename', (req, res) => {
Image.findOne({ image: req.params.filename }, (err, file) => {
// Check if the input is a valid image or not
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// If the file exists then it is an image
// Read output to browser
const readstream = Image.createReadStream(file.image);
readstream.pipe(res);
});
});
//for reading the multer image(it is important as first read the multer image with jimp read and then resize it and then delete the multer image)
app.get('/:image/:filename', (req, res) => {
if(req.params.image === "image"){
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
// Check if the input is a valid image or not
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// If the file exists then check whether it is an image
if (file.contentType === 'image/jpeg' || file.contentType === 'image/png') {
// Read output to browser
const readstream = gfs.createReadStream(file.filename);
readstream.pipe(res);
} else {
res.status(404).json({
err: 'Not an image'
});
}
});
}
});
app.delete('/files/:id', (req, res) => {
Image.deleteOne({_id: req.params.id}, function (err) {
if (err) {
console.log(err);
}
});
res.redirect("/")
});
app.listen(3000, () => console.log("Server started on port 3000"));

MongoDB query won't return object in my Express API (React)

I have done this so many times before, but I can't seem to find the issue, it's probably something small and stupid. Take a look at the /server.js file here! (Shortened for demonstration purposes)
/* Make Mongoose promise based */
mongoose.Promise = Promise;
mongoose.connect('mongodb://localhost:27017', options);
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error: '));
/* Routes */
app.route('/games')
.post(postGame)
.get(getGames);
app.route('/games/:id')
.get(getGame)
.delete(deleteGame);
app.route("*").get((req, res) => {
res.sendFile('client/dist/index.html', { root: __dirname });
});
const port = 8080;
app.listen(port, () => {
console.log(`Connected! Server listening on port: ${port}`);
});
Then for my Game model, I have that in app/models/game.js.
import mongoose from 'mongoose';
const Schema = mongoose.Schema;
const gameSchema = new Schema(
{
name: {
type: String,
required:true
},
year: {
type: Number,
required:true
},
description: {
type: String,
required:true
},
picture: {
type: String,
required:true
},
postDate : { type: Date, default: Date.now }
}
);
export default mongoose.model('Game', gameSchema);
This is where I believe I am having the issue.
/* Import Game model schema */
import Game from '../models/game';
const getGames = (req, res) => {
Game.find({}, (err, games) => {
console.log(err, games)
if (err) {
res.send(err);
}
res.json(games);
});
}
const getGame = (req, res) => {
const { id } = req.params;
Game.findById(id, (err, game) => {
if (err) {
res.send(err);
}
res.json(game);
});
}
const postGame = (req, res) => {
let game = Object.assign(new Game(), req.body);
game.save(err => {
if (err) {
res.send(err);
}
res.json({ message: 'Game successfully created!' });
});
};
const deleteGame = (req, res) => {
Game.remove(
{ _id: req.params.id },
err => {
if (err) {
res.send(err);
}
res.json({ message: 'Game successfully deleted!' });
}
);
};
export {
getGames,
getGame,
postGame,
deleteGame
};
Just do be clear... I went into the mongo shell.
I did...
connecting to: test
> db.createCollection('Game')
> db.Game.insert({name: "SSB", year: 2001, description: "Fun Game", picture: "http://google.com", postDate: "2017-01-03T08:51:45.888Z"});
And when I type > db.Game.find({}); I am returned with exactly what I have...
{
"_id" : ObjectId("58c2223e32daa04353e35bdc"),
"name" : "SSB",
"year" : 2001,
"description" : "Fun Game",
"picture" : "http://google.com",
"postDate" : "2017-01-03T08:51:45.888Z"
}
You see when I go to http://localhost:8080/games I am returned with an empty JSON and I just wanna know why. I am 70% sure, it is because it isn't connected to the right collection but I don't remember how to test that :(
I wanted to make this a comment but it won't let me because I don't have a 50 reputation, but I believe I found the issue.
const getGame = (req, res) => {
const { id } = req.params;
Game.findById(id, (err, game) => {
if (err) {
res.send(err);
}
res.json(game);
});
}
In this piece of code you are setting the id to req.params, but you need to set it to req.params.id which is what you passed in your route.
Should look like this:
const {id} = req.params.id;
If you logged id, you would probably get an object that says:
{ id: "[whatever_id_you_put_here]" }
however if you log req.params.id you should get the correct id you put in that spot..
The reason you're getting [] is because you're actually connected to the database and you are actually trying to "get" something, but that something doesn't exist so it sends an empty response.
I hope this helps..