Implementing Deposit using MongoDB and Node.JS - javascript

So when i make a request to an endpoint such as this http://localhost:3000/api/auth/get-info/email#example.com
using this code
The Model looks thus :
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema({
email: {
type: String,
required:true,
max: 255,
},
password: {
type: String,
required:true,
max: 2055,
},
phone: {
type: String,
required:true,
max: 255,
},
balance: {
type: mongoose.SchemaTypes.Number,
required:true,
},
fullname: {
type: String,
required:true,
max: 250,
},
created_at: {
type: Date,
default: Date.now(),
},
});
module.exports = mongoose.model('User',userSchema);
The code to utilise the model looks thus
const router = require("express").Router();
const User = require("../models/User"); // <----------- this is the model that saves the data to the Database
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
router.get("/get-info/:email", async (req, res) => {
try {
if (
!req.headers.authorization ||
!req.headers.authorization.startsWith("Bearer ") ||
!req.headers.authorization.split(" ")[1]
) {
return res.status(422).json({ message: "Please Provide Token!" });
}
const user = await User.find({ email: req.params.email });
res.status(200).json(user);
} catch (error) {
res.status(404).json({ message: error.message });
}
});
module.exports = router;
i get this as response
[
{
"_id": "63a1bf35d7622f37a569405a",
"email": "john_kross2#yopmail.com",
"password": "$2b$10$LFhAxdgu9aARyMkwNWXqs.unaf.vFAfUgWjfT6uK16wF/wwDN0oFS",
"phone": "08098777600",
"balance": 0,
"fullname": "Lucas Osman",
"created_at": "2022-12-20T13:52:49.442Z",
"__v": 0
}
]
How do i make a simple request, in this case that i would be able to make a request, get the balance as response, then use the balance to add to the amount and update the data in MongoDB database. A snippet may be very useful here.
I tried to call the Data from the above, then use amount in req.body.amount and add to the data from the database and use it to update the balance. Does not work as I expect.

Related

Problem with getting average rating from mongodb in node.js express

I have a node.js express back-end with a mongodb database on the cloud(mongodb atlas).
This is the Post object and I want to get the average grade from reviewerComments and userComments.
import mongoose from 'mongoose'
const postSchema = mongoose.Schema({
game: {
},
reviewerComments: [
{
author: String,
authorEmail: String,
avatar: String,
title: String,
text: String,
grade: Number,
date: String
}
],
userComments: [
{
author: String,
authorEmail: String,
text: String,
grade: Number,
date: String
}
]
}, {
timestamps: true
})
const Post = mongoose.model('Post', postSchema)
export default Post
I have a API route that calls this function
export const getAverageGrades = async (req, res) => {
const { id } = req.query
try {
const post = await Post.aggregate([
{
$match:
{
_id: mongoose.Types.ObjectId(`${id}`)
}
},
{
$unwind: "$reviewerComments"
},
{
$group:{
_id:{
"comment_id": "$reviewerComments.id",
"title": "$reviewerComments.title",
"grade": "$reviewerComments.grade",
},
avg_rating: {$avg:"reviewerComments.grade"}
}
},
{
$project:{
"id": "$_id.rating_id",
"title": "$_id.title",
"avg_rating": "$avg_rating" // avg_rating returns null
}
}
])
res.status(200).json(post);
} catch (error) {
console.log(error.message)
res.status(404).json({ message: error.message });
}
}
This function is returning a response where avg_rating is null, what am I doing wrong?

Get all duplicate keys from a POST request with mongoose

I decided to give typescript a try and make a small authentication API with express. What I wanted to do now is, make the username and email unique, so my mongoose schema looks as follows:
import * as mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
username: {
type: String,
required: [true, 'Username is required!'],
unique: true,
min: 6,
max: 255,
},
email: {
type: String,
required: [true, 'Email is required!'],
unique: true,
min: 6,
max: 255,
},
password: {
type: String,
required: [true, 'Password is required!'],
min: 6,
max: 1024,
},
date: {
type: Date,
default: Date.now(),
},
});
export const User = mongoose.model('User', userSchema);
My controller is also very simple:
export async function registerUser(
req: express.Request,
res: express.Response,
): Promise<express.Response> {
const user = new User({
username: req.body.username,
email: req.body.email,
password: req.body.password,
});
const error = user.validateSync();
if (error) {
return res.status(400).json(error);
}
await user.save(function (err) {
if (err) {
return res.status(400).send(err);
}
return res.status(200).send({ success: true, message: 'User created!' });
});
}
This all works as expected, however, if I do a POST request, where both the email and username already exist in the database, I do not get a response with both of them in the body. For example if I make a POST request with:
{
"username": "username2",
"email": "emailblabla2",
"password": "password1234"
}
where username2 and emailblabla2 have already been used, I will first get:
{
"driver": true,
"name": "MongoError",
"index": 0,
"code": 11000,
"keyPattern": {
"username": 1
},
"keyValue": {
"username": "username2"
}
}
as a response and at the second attempt I will get the same but for the email.
Is it possible to get both at the same time? Should I even be using mongoose to validate my data? I see a lot of people recommending joi, however, I thought if mongoose is already capable of doing that, why use an additional library for it.

Push To Mongoose Subdocuments

Hello I am creating a series of groupings describing the roles certain users are taking within the context of helping a client. The object in the Prospect model is called caseworkers. In caseworkers is a series of arrays for the different types of roles done. The equation is to allow the user to push his info as a subdocument called CaseWorker. Basically creating an object with 6 arrays that users can push to. Ive tried a few things and settled on Subdocuments. Any help would be awesome.
Here is my code:
const mongoose = require("mongoose");
const CaseWorker = require("./CaseWorker");
const ProspectSchema = mongoose.Schema({
caseWorkers: {
originators: [CaseWorker.schema],
loanProcessors: [CaseWorker.schema],
documentProcessors: [CaseWorker.schema],
upsells: [CaseWorker.schema],
primaryReso: [CaseWorker.schema],
taxPreparers: [CaseWorker.schema],
secondaryReso: [CaseWorker.schema],
}
module.exports = mongoose.model("prospect", ProspectSchema);
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const CaseWorkerSchema = new Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
role: { type: String },
resoCred1: { type: String },
resoCred2: { type: String },
reminders: [
{
_id: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
userReminded: { type: mongoose.Schema.Types.ObjectId },
reminderDate: { type: Date },
reminderDueDate: { type: Date },
status: { type: String },
daysTilDue: { type: Number },
id: { type: String },
text: { type: String },
clientId: { type: mongoose.Schema.Types.ObjectId, ref: "Prospect" },
},
],
});
module.exports = mongoose.model("caseWorker", CaseWorkerSchema);
router.put("/:_id/caseWorkers/loanProcessors", auth, async (req, res) => {
const prospect = await Prospect.findByIdAndUpdate(req.params._id, {
"$push": {
"loanProcessors": {
"caseWorker": {
"name": req.body.name,
"email": req.body.email,
"role": req.body.role,
"resoCred1": req.body.resoCred1,
"resoCred2": req.body.resoCred2,
},
},
},
});
res.json(prospect);
console.log(prospect);
});
In your approach when updating the document you put caseWorker under loanProcessors but it's declared in the schema the other way around.
To update a nested object you have to use the dot notation to reference the field.
Don't forget to put the object key that represent the field as a string like this "caseWorkers.loanProcessors", because caseWorkers.loanProcessors is an invalid object key in javascript
"$push": {
"caseWorkers.loanProcessors": {
"name": req.body.name,
"email": req.body.email,
"role": req.body.role,
"resoCred1": req.body.resoCred1,
"resoCred2": req.body.resoCred2,
},
},

Try to populate in mongoose and it doesn't work (nodejs)

i Make mini cart with Product and user Auth, Evereting work perfect but whan i try to make a route that pickup all the product from the user and view them in specific page and it not work for me.
it returns the user but not the product.
UserSchema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema({
product: {
type: [mongoose.Schema.Types.ObjectId],
ref: "product"
},
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
address: {
type: String,
required: true
},
password: {
type: String,
required: true
},
data: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("user", UserSchema);
ProductScheama
const mongoose=require('mongoose');
const ProductSchema = new mongoose.Schema({
name:{
type:String,
required:true,
unique:true
},
description:{
type:String,
},
price:{
type:Number,
required:true
},
quantity:{
type:Number,
required:true
},
data:{
type:Date,
default:Date.now
}
})
module.exports=Product=mongoose.model('product',ProductSchema)
I am trying to create a function that gives me the name, price and description of the product and it fails.
my router:
router.get("/products/:id", auth, async (req, res) => {
try {
let pro = await User.find({ product: req.params.id }).populate("product", [
"name",
"price",
"description"
]);
if (!pro) {
return res.json({ msg: "This user not have products to show" });
}
res.json(pro);
} catch (err) {
console.error(err.message);
res.status(500).send("Server errors");
}
});
result from Postman:
[
{
"product": [],
"_id": "5d5bfb96963ca600ec412bca",
"name": "Anonny Annon",
"email": "Annony#gmail.com",
"address": "Israel",
"password": "$2a$10$gESTIaBVifzhRDR2zOKsw.Q79gCT07IK2VnDoyT2oU5htqfBuAj8W",
"data": "2019-08-20T13:54:30.267Z",
"__v": 0
}
]
I think product should be defined this way :
product: [{
type: mongoose.Schema.Types.ObjectId,
ref: "product"
}]
instead of type: [mongoose.Schema.Types.ObjectId]
Solution found here

Can't get populate() to fill out array in Mongoose

Let me begin by saying I know that this seems to be a frequently asked question and I've spent a couple of days trying to figure it out but no answer seems to work so I'm trying on here.
I have two models, User and Chapter: a Chapter can have have many members (Users). When I do router.get('/chapters') I want to see an array of all the Users associated with a Chapter as a property along with the other Chapter properties, like so:
[
{
"leads": [],
"members": [
{"_id":"someString1","firstName":"...", "lastName":"..."},
{"_id":"someString2","firstName":"...", "lastName":"..."},
],
"date": "2018-12-12T15:24:45.877Z",
"_id": "5c11283d7d13687e60c186b3",
"country": "5c11283d7d13687e60c185d6",
"city": "Buckridgestad",
"twitterURL": "qui",
"bannerPic": "http://lorempixel.com/640/480/people",
"__v": 0
}
]
But what I'm getting is this:
[
{
"leads": [],
"members": [],
"date": "2018-12-12T15:24:45.877Z",
"_id": "5c11283d7d13687e60c186b3",
"country": "5c11283d7d13687e60c185d6",
"city": "Buckridgestad",
"twitterURL": "qui",
"bannerPic": "http://lorempixel.com/640/480/people",
"__v": 0
}
]
These are my Schemas:
Chapter
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create Schema
const ChapterSchema = new Schema({
country: {
type: Schema.Types.ObjectId,
ref: "countries"
},
city: {
type: String,
required: true
},
leads: [
{
type: Schema.Types.ObjectId,
ref: "users"
}
],
members: [
{
type: Schema.Types.ObjectId,
ref: "users"
}
],
twitterURL: {
type: String,
required: true
},
bannerPic: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now()
}
});
module.exports = Chapter = mongoose.model("chapters", ChapterSchema);
User
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create Schema
const UserSchema = new Schema({
username: {
type: String,
required: true
},
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
organisation: {
type: String,
required: true
},
chapter: {
type: Schema.Types.ObjectId,
ref: "chapters"
},
email: {
type: String,
required: true
},
admin: {
type: Boolean,
default: false
},
lead: {
type: Boolean,
default: false
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now()
}
});
module.exports = User = mongoose.model("users", UserSchema);
Like I said, when I call the endpoint, I want it to return me all the Chapters with all the Users as a populated property.
I've tried a lot of variations of .populate() but to know luck. The closest I got was going through the early levels of callback hell which I know isn't necessary with today's tech, but nothing is working!
My routes/api/chapters.js
// #route GET api/chapters
// #desc Get all Chapters
// #access Public
router.get("/", (req, res) => {
Chapter.find()
.populate("members")
.then(chapters => {
return res.json(chapters);
})
.catch(err =>
res.status(404).json({ nochaptersfound: "No Chapters found" })
);
});
I can get it to work the other way around:
My routes/api/users.js
// #route GET api/users
// #desc Return all users
// #access Public
router.get("/", (req, res) => {
User.find()
.populate("chapter")
.exec()
.then(users => res.status(200).json(users))
.catch(err => console.log(err));
Returns a user with the populated Chapter, but I can't populate the chapter.members array
Any help would be greatly appreciated!
Thanks!!
From your comment, I believe you are not actually storing users in your chapters. What you are doing is this:
User.create({..., chapter: id})...
And assuming chapter now has a user. Its not the way it works with mongoose, so if you want to actually save in both place, you will need to do it yourself. You are thinking about this as if it were a relational database
You will need to do something like:
const user = await User.create({..., chapter: id})
const chapter = await Chapter.findOne({ _id: id })
chapter.members.push(user)
chapter.save()
If your populate wasn't working, you'd not get an empty array, you'd get an array with ids. Your current populate query is fine, you just don't have any data to populate
With promises, it would look like this:
var userPromise = User.create({..., chapter: id}).exec()
var chapterPromise = Chapter.findOne({ _id: id }).exec()
Promise.all([userPromise, chapterPromise]).then((user, chapter) => {
chapter.members.push(user)
return chapter.save()
}).then(chapter => {
// send response
})
If you need 10 chapters with 10 to 50 users, I'd create 50 users, then push all of them into the chapters and save the chapter.

Categories

Resources