Insert data on already existing User in mongodb - node.js

Can anyone help me solve this problem, I've been stuck days on it and haven't found any solution to.
I have this user schema in my mongodb / node js:
const userSchema = new Schema({
username:{
type: String,
required: true,
unique: true,
},
name:{
type: String,
required: true,
},
password:{
type: String,
required: true,
},
phoneNumber:{
type: String,
required: true,
},
age:{
type: Number,
required: true,
},
helpSent: [Help.schema],
});
The helpSent is basically an array that stores every data the user has requested in the application.
Now by using my update function, which is the following:
exports.createHelp = async (req,res) => {
try{
const decoded = jwt.verify(req.headers.authorization.split(' ')[1], config.secret);
const help = new Help({
type: req.body.type,
description: req.body.description,
timeToRespond: req.body.timeToRespond,
emergencyLevel: req.body.emergencyLevel,
acceptance: req.body.acceptance,
state: req.body.state,
dateIssued: req.body.dateIssued
});
const user = await User.findOne({username: decoded.data});
user.helpSent.push(help);
const savedUser = await user.save();
res.json(savedUser)
}catch(e){
console.log({message: e});
}
}
I'm getting this error as if the function is storing a new data entry in the database and telling me that the username is already taken since I have it as a unique value
{
message: Error: user validation failed: _id: Username already in use.
at ValidationError.inspect (D:\Patrick\Flutter\Fyp\draft-v1\backend\node_modules\mongoose\lib\error\validation.js:48:26)
at formatValue (node:internal/util/inspect:763:19)
at formatProperty (node:internal/util/inspect:1681:11)
at formatRaw (node:internal/util/inspect:1006:9)
at formatValue (node:internal/util/inspect:793:10)
at inspect (node:internal/util/inspect:340:10)
at formatWithOptionsInternal (node:internal/util/inspect:2006:40)
at formatWithOptions (node:internal/util/inspect:1888:10)
at console.value (node:internal/console/constructor:323:14)
at console.log (node:internal/console/constructor:359:61) {
errors: { _id: [ValidatorError] },
_message: 'user validation failed'
}
}
Anyone help can help, and thank you!

Why dont you use updateOne
await User.updateOne({ username: decoded.data }, {
$push: {
helpSent: help
}
})
The first argument is the query condition, in your case you search for an username with decoded.data, and the second argument is your update logic

Related

Getting a JSON circular structure error when updating a model's field

I am building an e-commerce web application with NodeJS with express and MongoDB. I working on an API for storing a product id and quantity in an array that is the user's cart.
This is the user model:
const userSchema = mongoose.Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
username: {
type: String,
required: true
},
access_level: {
type: Number,
default: 1
},
cart: {
type: [cartProductSchema],
default: []
}
})
This is the model for cartProductSchema:
const cartProductSchema = new mongoose.Schema({
product_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product'
},
quantity: {
type: Number,
required: true,
validate: { validator: Number.isInteger }
}
}, { _id: false })
This is the model for the Product:
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
stock: {
type: Number,
required: true,
validate: { validator: Number.isInteger }
}
}, {timestamps: true})
Here is the snippet of the router where the error is.:
// Add product to user's cart
const product = await Product.findOne({_id: req.body.product_id})
if (!product) {
return res.status(http.statusNotFound).json({
errors: [{ msg: "Invalid product id" }]
})
}
let cart = user.cart.slice()
cart.push({ product_id: product._id, quantity: req.body.quantity })
user.cart = cart // this is the line that causes the error
await user.save()
res.json({ msg: "Product added to cart" })
I am getting an error when I try to push a JSON object with product_id and quantity into a user's cart. There is a circular reference in the JSON object that's causing it, but I can't figure out what I did wrong. The error stack trace doesn't really Here is the error I get:
TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property '__parentArray' -> object with constructor 'Array'
--- index 0 closes the circle
at stringify (<anonymous>)
If I uncomment, user.cart = cart line, then I don't get this error. The moment I try to update the cart field, I get this error. I tried updating the cart field in different formats, but all failed.
I tried directly pushing to the cart field, yet I get the same error:
user.cart.push({ product_id: product._id, quantity: req.body.quantity})
I also tried to directly update the cart with a MongoDB query, but I still get the same error:
await User.updateOne(
{_id: user._id},
{ $push: { cart: { product_id: product._id, quantity: req.body.quantity } }}
)
I figured out what the problem was. Sorry for the trouble. I should've mentioned I was testing the API with jest tests. Turns out there was an error in the tests, that I was able to debug after adding a --detectOpenHandles tag to the npm test script.

Referencing a document from another database in mongoose?

How can I reference a document from another database?
This is how I'm connecting to the databases as mentioned in the docs (Docs):
import mongoose from "mongoose";
export default async function connect() {
const usersConn = await mongoose
.createConnection(process.env.USERS_MONGO_URI)
.asPromise(); // Wait for the connection to be created
const videosConn = await mongoose
.createConnection(process.env.VIDEOS_MONGO_URI)
.asPromise(); // Wait for the connection to be created
const User = usersConn.model(
"User",
new mongoose.Schema({
id: {
type: String,
required: true,
},
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
})
);
const Video = videosConn.model(
"Video",
new mongoose.Schema({
title: {
type: String,
required: true,
},
path: {
type: String,
required: true,
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
})
);
return {
usersClient: usersConn.getClient(), // For next-auth
User,
Video,
};
}
But when I try to populate my query:
const video = await Video.findById(
new mongoose.Types.ObjectId(id as unknown as string)
)
.populate("author")
.exec((err, v) => {
console.log(err, v);
});
It gives me the following error:
MissingSchemaError: Schema hasn't been registered for model "User".
Use mongoose.model(name, schema)
I've been trying to look for this for a long time, but I'm unable to find an answer. The way I solved this, although a bit hacky, is by saving the id in a field called author_id, then searching through the User model for the id when querying.

mongoose .save() doesn't work on a specific collection

so I'm trying to create a party with creator field with id of a user, and at the same time adding a party id to users parties using mongoose sessions. Here's the code of a request:
const createParty = async (req, res, next) => {
const {title, description, address, creator} = req.body;
const createdParty = new Party({
title,
description,
image: 'https://media-cdn.tripadvisor.com/media/photo-s/14/03/b3/4e/tlv.jpg',
address,
creator,
savedBy: []
});
let user;
try {
user = await User.findById(creator);
} catch (err) {
let error = new HttpError('Fetching user failed', 500);
return next(error);
}
if (!user) {
return next(new HttpError('Could not find user for providen id', 404));
}
try {
const sess = await mongoose.startSession();
sess.startTransaction();
await createdParty.save({ session: sess });
user.parties.push(createdParty);
console.log(user);
await user.save({ session: sess });
await sess.commitTransaction();
} catch (err) {
let error = new HttpError('Creating party failed', 500);
return next(error);
}
res.status(201).json({party: createdParty});
};
And my user and parties schemas:
const userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, minlength: 6 },
image: { type: String, required: true },
parties: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Party' }],
savedParties: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Party' }]
});
const partySchema = new Schema({
title: { type: String, required: true },
description: { type: String, required: true },
image: { type: String, required: true },
address: { type: String, required: true },
creator: { type: mongoose.Types.ObjectId, required: true, ref: 'User' },
savedBy: [{ type: mongoose.Types.ObjectId, required: true, ref: 'User' }]
});
The problem is I can't save a user with new party id, only this line fails:
await user.save({ session: sess });. Tried to move this line to a separate try/catch, tried to add user.markModified('parties'); didn't help. Please help those who may know the solution.🙏🏻
UPDATE ON THE PROBLEM
So I did some testing and found out that if I delete everything from the database, and I'll create a user I will be able to add parties, and it'll work as it should. But if I'll create another user and afterward will try to add a party to one of the users it won't work.
when you session it won't create the collection if it doesn't exist and you need to do it manually in the data

i want to query all the document using findById query ( Ref ObjectId ) in mongoose

currently building notes-app project where we can save notes and can edit and delete notes also..
suddenly got stuck here... i want to query ( findById ) all the documents that matches with user id.. in this case i referenced user id as postedBy in Notes Schema..
here is my user schmea or model...
import mongoose from 'mongoose'
const userSchema = new mongoose.Schema({
username: {
type: String,
required: [true, 'please provide username'],
},
email: {
type: String,
required: [true, 'please provide email'],
unique: true,
index: true,
},
password: {
type: String,
required: [true, 'please provide password'],
},
accountCreatedAt: {
type: String,
default: Date,
},
})
const User = mongoose.model('User', userSchema)
export default User
here goes my notes Schema and i referenced user id as ref :
import mongoose from 'mongoose'
const noteSchema = new mongoose.Schema(
{
title: {
type: String,
required: [true, 'please provide title'],
unique: true,
trim: true,
},
text: {
type: String,
trim: true,
required: [true, 'Please provide text'],
},
lable: {
type: String,
required: [true, 'please provide lable'],
},
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true,
},
},
{
timestamps: { createdAt: 'created_At', updatedAt: 'updated_At' },
}
)
const Note = mongoose.model('Note', noteSchema)
export default Note
route and controller function:
noteRoutes.get('/getNotesByUserID/:_id', noteController.getNotesByUserID)
export const getNotesByUserID = async (req, res, next) => {
try {
const id = req.params._id
const userNotes = await Note.findById({ postedBy: id })
res.status(200).json({
status: 'success',
data: {
userNotes,
},
})
} catch (error) {
res.status(400).json({
status: 'error',
data: {
message: error.message,
},
})
}
}
when i tried to test this in postman i'm getting the below message :
*"message": "Cast to ObjectId failed for value \"{ postedBy: '609554f9560327264b23d3fe' }\" at path \"_id\" for model \"Note\""*
thanks in advance...
mongoose findById method casts the id parameter to the type of the model's _id field, in your case this field is an ObjectID type.
You however are passing the id argument as an object { postedBy: '609554f9560327264b23d3fe' } then mongoose tries to do the following:
const castId = new ObjectId({ postedBy: '609554f9560327264b23d3fe' })
This fails for obvious reasons.
Because findById is a customized method to "quickly" find documents by their _id field you shouldn't be using it to query a different field. In your cast you should be using findOne instead.
const userNotes = await Note.findOne({ postedBy: id })

Prevent server from crashing while interacting with db

I'm trying to create login form using mongoose. The error has been occurred when I try to find for example an email in my database an it doesn't exist. In this case my app crashed.
Here is my UserSchema:
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
credit:{
type: Number,
default:0
},
email: {
type: String,
unique: true,
required: true,
trim: true
},
telegramId:{
type: String,
trim: true,
required: true
},
password: {
type: String,
required: true
},
inboxMessages: {
type: Array
},
submittedBooks:{
type: Array
},
profilePicture: {
type: String,
default: '/'
}
});
var User = mongoose.model('User', userSchema);
module.exports = User;
and this is my NodeJS code and query:
UserModel.find({name: 'akbar'}, (err, data) =>{
if (err) {
console.log(err);
}
else{
console.log(data[0].password);
}
})
UserModel.find({name: 'akbar'}, ....) cause an error which contains TypeError: Cannot read property 'password' of undefined. How can I prevent crashing my app?
When you try to find an object from the database, there might be 3 scenarios.
Internal server error (You checked this).
Empty or null value. (You have not checked it yet).
Got the desired object. (You print these values)
So to checked scenario 2, use the following code,
UserModel.find({name: 'akbar'}, (err, data) =>{
if (err) {
console.log(err);
} else if ((!data) || (data.length <= 0)) {
console.log('No objecct exist');
} else{
console.log(data[0].password);
}
})
In your NodeJS did you import as
var userModel = require('place_you_defined_the_model')
else, if its just import, like import('place_you_define_model')then you should use,
user.find({name:'Akbar'})

Resources