mongoose ^6.0.12 findandupdate on models with required fields - node.js

I have updated my mongoose to version 6.0.12 but since that all usually workings findoneandupdate operations on models that have required fields and other validations rules stopped working
try {
await UserModel.findByIdAndUpdate(
req.body.userId,
{ $set : {picture: "./uploads/profile/" + fileName}},
{ new: true, upsert: true, setDefaultsOnInsert: true},
(err, docs) => {
if (!err) return res.send(docs);
else return res.status(500).send({ message: err });
}
);
} catch (err) {
return res.status(500).send({ message: err });
}
onst userSchema = new mongoose.Schema(
{
pseudo: {
type: String,
required: true,
minLength: 3,
maxLength: 55,
unique: true,
trim: true
},
email: {
type: String,
required: true,
validate: [isEmail],
lowercase: true,
unique: true,
trim: true,
},
password: {
type: String,
required: true,
max: 1024,
minlength: 6
},
picture: {
type: String,
default: "./uploads/profile/random-user.png"
},
bio :{
type: String,
max: 1024,
},
followers: {
type: [String]
},
following: {
type: [String]
},
likes: {
type: [String]
}
},
{
timestamps: true,
}
);
I got this errors just after the updrade
"originalStack": "Error\n at model.Query._wrappedThunk [as _findOneAndUpdate] (C:\Users\amen\NODE\mern-project\node_modules\mongoose\lib\helpers\query\wrapThunk.js:25:28)\n
at
C:\Users\amen\NODE\mern-project\node_modules\kareem\index.js:279:20\n
at _next
(C:\Users\amen\NODE\mern-project\node_modules\kareem\index.js:103:16)\n
at
C:\Users\amen\NODE\mern-project\node_modules\kareem\index.js:508:38\n
at processTicksAndRejections
(internal/process/task_queues.js:77:11)"
thank you in advance
Regards

Related

res.json() returns { acknowledged: false }

I am trying to update an array, nested within an object in MongoDB document, using mongoose.
I have been over several similar questions, and only appeared to make a little success, then res.json return { acknowledged: false }, with no errors.
The goal is to push an object into the "likes" array inside reactions object
This is the document that I'm trying to update
_id: new ObjectId("63179b818ebed9da5b433ee0"),
thoughtText: "If Everything works out here, we're supposed to get a notification send to another guy by whomsoever leaves a comment or a like on this post.",
topic: 'Testing out the new notification codes for possible errors',
username: 'anotherguy',
userId: '63179a67849b0348e59d4338',
category: 'Secrets',
createdAt: 2022-09-06T19:12:01.345Z,
reactions: [
{
CommentLikeCount: 0,
mentions: 0,
reactionBody: 'Welcome to U-annon anotherGuy, this is your official first reaction on the site',
username: 'marryGold',
_id: new ObjectId("63179cd18ebed9da5b433ee8"),
reactionId: new ObjectId("63179cd18ebed9da5b433ee9"),
createdAt: 2022-09-06T19:17:37.829Z,
likes: []
},
Below is the query I'm currently using to update the document using updateOne.
EDIT: The schema.
// thought schema or post schema
const thoughtSchema = new Schema (
{
thoughtText: {
type: String,
required: true,
minlength: 1,
maxlength: 2000
},
topic:{
type: String,
required: true,
minlength: 1,
maxlength: 300
},
createdAt: {
type: Date,
default: Date.now,
get: createdAtVal => moment(createdAtVal).startOf('hour').fromNow()
},
username: {
type: String,
required: true,
},
userId:{
type: String,
required: true
},
category: {
type: String,
required: true,
},
reactions: [reactionSchema],
likes: [likeSchema],
},
{
toJSON: {
virtuals: true,
getters: true,
},
id: false,
}
The like schema is similar to the reaction schema,
//reaction schema
const reactionSchema = new Schema (
{
reactionId: {
type: Schema.Types.ObjectId,
default: () => new Types.ObjectId(),
},
reactionBody: {
type: String,
required: true,
},
username: {
type: String,
required: true,
},
userId:{
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now,
get: createdAtVal => moment(createdAtVal).startOf('second').fromNow()
},
mention: {
type: Object,
required: false
},
likes: [likeSchema],
CommentLikeCount: {
type: Number,
default: 0,
},
mentions: {
type: Number,
default: 0
}
},
{
toJSON: {
virtuals: true,
getters: true
},
id: false,
}
)
And this is the full controller function. including how I check to see if the same user already liked the comment
//Like comments
async likeComments(req, res){
console.log(req.body, req.params)
try {
const post = await Thought.findById(req.params.thoughtId)
const comment = post.reactions.find(x => x.reactionId.toString() === req.params.reactionId)
const liked = comment.likes.find(x => x.username === req.body.username)
if(!liked){
console.log('its open')
const data = await post.updateOne({"reactions.[reaction]._id": req.params.reactionId}, {$addToSet:{"reactions.$.likes": req.body}}, { runValidators: true, new: true })
console.log(data)
res.json(data)
}else{
console.log('already liked')
const data = await post.updateOne({"reactions.[reaction]._id": req.params.reactionId}, {$pull:{"reactions.$.likes": req.body}}, { runValidators: true, new: true } )
res.json(data)
}
} catch (error) {
console.log(error)
}
I've on this for the entire day, I'd really appreciate any help that I can get.

MongoDB mongoose filter with gender where user in profile is objectID

I am new in backend development.
I am trying to create profile endpoints to get all profiles with the gender of the user is either male or female.
Profile contains user as a objectID.
I want to filter profiles using users gender.
My UserSchema looks like this
const userSchema = mongoose.Schema(
{
firstname: {
type: String,
required: true,
trim: true,
},
lastname: {
type: String,
required: true,
trim: true,
},
email: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Invalid email');
}
},
},
password: {
type: String,
required: true,
trim: true,
minlength: 8,
validate(value) {
if (!value.match(/\d/) || !value.match(/[a-zA-Z]/)) {
throw new Error('Password must contain at least one letter and one number');
}
},
private: true, // used by the toJSON plugin
},
role: {
type: String,
enum: roles,
default: 'user',
},
gender: {
type: String,
enum: genders,
required: true,
},
profileStatus: {
type: String,
enum: profileStatus,
default: 'inProgress',
},
isEmailVerified: {
type: Boolean,
default: false,
},
},
{
timestamps: true,
}
);
And Profile schema looks like this
const profileSchema = new Schema(
{
user: { type: Schema.Types.ObjectId, ref: 'User', required: true, unique: true },
bio: { type: String, required: true },
profilePicUrl: {
type: String,
required: true,
},
birthdate: {
type: Date,
required: true,
},
profession: {
type: String,
required: true,
},
profileCompletion: {
type: Number,
default: 50,
min: 0,
max: 100,
},
credits: {
type: Number,
default: 2,
min: 0,
},
lastLogin: {
type: Date,
default: new Date(),
required: true,
},
},
{ timestamps: true }
);
I want to find profiles where user gender is male or female.
How can I do that?
You can create a endpoint like this and use .find() to find all the users with the gender passed by user
router.get(/user/:gender, async (req, res) => {
try {
const users = await User.find({ gender: req.params.gender }).exec();
res.status(200).json(users);
} catch (err) {
return res.status(500);
}
})

How to correctly save references to mongodb from request

I want to save data and references of child document into parent document from request, I have managed to achieve that, but I am not sure is this correct way of doing it.
I have found in stackoverflow that first we have to save child document. so we can save references of child document into parent document
This is my structure of request
"category": "movie",
"overview": "This is overview",
"poster_path": "https://image.tmdb.org/t/p/w500/aWeKITRFbbwY8txG5uCj4rMCfSP.jpg",
"release_date": "2021-12-01",
"title": "Sing 2",
"vote_average": 8.2,
"cast": [
{
"name": "Matthew McConaughey",
"profile_path": "wJiGedOCZhwMx9DezY8uwbNxmAY.jpg"
},
{
"name": "Reese Witherspoon",
"profile_path": "6Pp3BrY2JbJg77Po8NOBO6zOA8m.jpg"
}
]}
//Show Schema
const showSchema = new Schema({
title: {
type: String,
unique: true,
required: [true, 'Title can not be empty.'],
trim: true,
text: true
},
slug: String,
poster_path: {
type: String,
required: [true, 'Cover can not be empty.'],
trim: true
},
overview: {
type: String,
required: [true, 'Description can not be empty.'],
trim: true,
text: true
},
release_date: {
type: Date,
default: Date.now(),
required: [true, 'Release date can not be empty.']
},
category: {
type: String,
trim: true,
required: [true, 'Please provide category']
},
vote_average: {
type: Number,
min: [1, 'Rating must be 1 or above 1'],
max: [10, 'Rating must be 10 or below 10']
},
vote_count: {
type: Number,
default: 0
},
cast: [
{
type: mongoose.Schema.ObjectId,
ref: 'Cast'
}
]
})
//Create slug
showSchema.pre('save', function(next) {
this.slug = slugify(this.title, {lower: true})
next()
})
showSchema.pre(/^find/, function (next) {
this.populate({
path: 'cast',
select: '-__v'
})
next()
})
//Cast Schema
const castSchema = new Schema({
name: {
type: String,
trim: true,
text: true,
unique: true,
required: [true, 'Please provide name of actor']
},
profile_path: {
type: String
}
})
And this is how I did it
exports.add = async (req, res) => {
const show = {
category: req.body.category,
overview: req.body.overview,
poster_path: req.body.poster_path,
release_date: req.body.release_date,
title: req.body.title,
vote_average: req.body.vote_average,
}
try {
Cast.insertMany(req.body.cast, function(error, createdCast){
if(error){
console.log('Cast', error)
return
}
Show.create(show, function(error, createdShow){
if(error){
console.log('Show', error)
return
}
createdCast.forEach(element => {
createdShow.cast.push(element._id)
});
createdShow.save(function(error, show){
if(error){
return
}
console.log('saved Show', show)
})
})
})
} catch (error) {
console.log(error)
res.status(400).json({
message: 'fail',
error: error
})
}
}

Add data in an array of object with mongoDB

I need your help, I try to add(if it not exists) or update if exists datas in an array of Object in MongoDB.
Here is my Model
import { Schema, model } from "mongoose";
const userSchema = new Schema({
firstName: {
type: String,
required: true,
unique: false,
trim: true
},
pseudo: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
email: {
type: String,
required: false,
trim: true
},
password: {
type: String,
required: true
},
// password2: {
// type: String,
// required: true
// },
tags: {
type: Array,
required: false
},
address: {
type: String,
required: true,
unique: false,
trim: true
},
coord: {
type: Object,
required: false,
unique: false,
trim: true
},
poll: [
{
tag: String,
dates: Array
}
]
},
{
timestamps: true,
});
const User = model('User', userSchema);
export default User;
My route
router.route('/calendar/:email').post((req, res) => {
User.findOne({ email: req.body.email }).then( (user) =>{
console.log("user 1", user)
User.bulkWrite([
{
insertOne: {
"poll": {
"tag": req.body.selectedTag,
"dates": req.body.datesArray
}
}
},
{
updateOne: {
"filter": {
"tag" : req.body.selectedTag
},
"update": {
$set: {
"dates": req.body.datesArray
}
},
}
}
])
})
});
and the datas sended :
email: 'john#gmail.com',
selectedTag: 'work',
dateArray: [ '2020-07-16T22:00:00.000Z' ]
I try many things like by findOneaAndUpdate, but I don't know how to add in the array "poll", objects with tag and the dates associated.
If somebody could help me it would be very nice !
I shoul use add $addToSet or $push, depending if the element is unique or not.
Something like this:
"update": {
"$addToSet": {
"poll": { /*...*/ }
}
}
For reference:
http://docs.mongodb.org/manual/reference/operator/update/addToSet/
http://docs.mongodb.org/manual/reference/operator/update/push/

mongodb error no documents found

Here is my code to find winners of a contest :
var date = moment().subtract('days', 1).format("YYYY-MM-DD");
console.log(date)
Contest.findOne({date: date}, function(err, contest){
if(!err){
if(contest){
Participant.find({ questionID : contest._id, random : { $near : [Math.random(), 0] } }).limit(5).exec(function(err, participants){
async.map(participants, function(participant, callback) {
contest.winners.push(participant)
contest.save(function(err) {
callback(err);
})
}, function(err) {
if (!err) {
console.log("Added winners to contest")
} else
console.log(err)
});
});
}
else{
console.log("No contest found")
}
}
else{
console.log(err)
}
})
Schema :
var ContestSchema = new Schema(
{
question:{
type: String,
trim: true
},
answers:[{
option: {type: String},
correct: {type: Boolean, default : false}
}],
date: {
type: String,
trim: true
},
priority: {
type: Number,
trim: true,
default : 0
},
winners : [{
type: Schema.Types.ObjectId,
ref: 'Participant'
}]
})
/*
*Participant Schema
*/
var ParticipantSchema = new Schema(
{
questionID:{
type: String,
trim: true
},
userID:{
type: String,
trim: true
},
name:{
type: String,
trim: true
},
email:{
type: String,
trim: true
},
mobile:{
type: String,
trim: true
},
address:{
type: String,
trim: true
},
landmark:{
type: String,
trim: true
},
city:{
type: String,
trim: true
},
state:{
type: String,
trim: true
},
random:{
type: [Number],
default : [Math.random(), 0],
index: '2d'
}
})
mongoose.model('Contest', ContestSchema)
mongoose.model('Participant', ParticipantSchema)
While saving winners to the contest, it saves the winners, but I am getting error :
{
"status": {
"error": 1,
"message": {
"message": "No matching document found.",
"name": "VersionError"
}
}
}
What is this error and how can I solve this ?
I would try rewriting the async.map operation. This would result in a single call to contest.save and you don't have to fear any race conditions.
async.map(participants, function(participant, callback) {
contest.winners.push(participant)
callback();
}, function(err) {
contest.save(function(err) {
if (!err) {
console.log("Added winners to contest")
} else {
console.log(err)
}
});
});

Resources