findOneReplace replacment issue - javascript

I want to find a document in my db and replace it with a document that has a new name and new key.
Here is my Schema
const Schema = mongoose.Schema;
const vampireSchema = new Schema({
name: { type: String, required: true },
title: String,
hair_color: {type: String, default: "blonde" },
eye_color: String,
dob: Date,
loves: [String],
location: String,
gender: String,
victims: {type: Number, min: 0}
});
const Vampire = mongoose.model("Vampire", vampireSchema);
module.exports = Vampire;
Here is my executable code
Vampire.findOneAndReplace( { name: "Claudia" }, { name: "Eve", portrayed_by: "Tilda Swinton" }, (err, vamp) => {
if(err){
console.log(err)
}
else{
console.log(vamp)
}
db.close()
})

There are two issues that I can see.
First, you should pass null as the third argument in your findOneAndReplace call. This will set the options to null and should get your code running. This is in my opinion a strange behavior of mongoose.
Vampire.findOneAndReplace(
{ name: "Claudia" },
{ name: "Eve", portrayed_by: "Tilda Swinton" },
null,
(err, vamp) =>
{
if(err){
console.log(err)
}
else{
console.log(vamp)
}
db.close()
})
Secondly, I would recommend adding the portrayed_by to the schema, otherwise, that field will not be in the newly created document. Therefore, I would adjust your schema that way:
const vampireSchema = new Schema({
name: { type: String, required: true },
title: String,
hair_color: {type: String, default: "blonde" },
eye_color: String,
dob: Date,
loves: [String],
location: String,
gender: String,
victims: {type: Number, min: 0},
portrayed_by: String
});

Related

Default values not adding to mongoose Model

So this is an example of my schema I have for a user.
id: String,
email: String,
slug: {
type: Object,
phrase: {type: String, default: null},
},
When I want to define a new user and save that user, I would do the following;
const newUser = new User({
id: 123,
username: "CoolUser",
email: "BillGates#google.com"
});
newUser.save();
But this does not save the "slug" object, It was my understanding, that since I a default value for it, it would auto populate with that default value. What can I do to make it auto generate without having to define the whole schema again when saving a user?
You should add default for slug property, and not for his sub-property. Try changing your schema like this:
slug: {
type: {
phrase: { type: String },
},
default: {
phrase: null
},
},
try this:
const subschema = new Schema({
phrase: {type: String, default: null},
}, { _id: false });
and in your original schema:
id: String,
email: String,
slug: {
type: subschema,
default: () => ({})
},
this should do the trick.
const User = new Schema({
id: String,
about: {
bio: String,
location: String,
website: String,
discord: String,
twitter: String,
default: {
bio: "This is a default bio.",
location: "",
website: "",
discord: "",
twitter: "",
}
}
})
Ok here is the example, I removed some stuff from it just for ease, Basically as you can see I want bio to default to: This is a default bio.
But instead, I get the following error:
throw new TypeError(`Invalid schema configuration: \`${name}\` is not ` +
^
TypeError: Invalid schema configuration: `This is a default bio.` is not a valid type at path `about.default.bio`. See bit ly / mongoose-schematypes for a list of valid schema types.

Destructuring a mongoose document

Using mongoose in my project, I ran into a problem.
I want to find all documents that have such a key and value pair role: USER. I can get a list of documents, but I cannot get the values of specific fields from it, no matter how I try.
Here is my code:
const getUsersList = async () => {
const users = await userModel.find({ role: USER });
//also I truing:
//In each case, I get undefined
const users = await userModel.find({ role: USER }).userName;
////
const users = await userModel.find({ role: USER }).exec();
////
Document.prototype.toObject(users);
////
JSON.stringify(users).userName
}
The request definitely gets the document, because console.log(users) lists the documents.
[
{
_id: new ObjectId("618b1a587d57e9c8e78865e1"),
userName: 'Username1',
name: 'Fullname1',
email: 'email1#gmail.com',
password: 'Password1',
status: 'INVITED',
role: 'USER',
__v: 0
},
{
_id: new ObjectId("618b1a6e7d57e9c8e78865e5"),
userName: 'Username3',
name: 'Fullname2',
email: 'email2#gmail.com',
password: 'Password2',
status: 'INVITED',
role: 'USER',
__v: 0
}
]
Judging by the documentation of the mongoose, I am doing everything right. It is also advised to cast a document into an object using toObject(), but mongoose does not find such a method for request
Моя схема:
const userSchema = new Schema(
{
userName: { type: String, unique: true, required: true },
name: { type: String, required: true },
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
confirmationCode: { type: String, required: false },
status: { type: String, required: true, default: STATUS.INVITED },
role: { type: String, required: true, default: USER },
},
);
It's an array, so trying to get userName won't work. You need to get the specific element. Try this:
const userResponse = await userModel.find({ role: USER })
const firstUserName = userResponse[0].userName

Referencing Other Models when Saving Data Express/Mongoose

I have a simple express app where users can log in and post pictures of mountains. I'm having an issue saving the posts the users add. Specifically, the user id that is referenced from another schema(user schema). When I submit the form, I get an undefined error on the "._id" and I'm not sure how to go about fixing it.
Below are my model schemas.
const userSchema = new Schema({
name: String,
email: String,
username: String,
password: String,
});
const canyonSchema = new Schema({
canyon: String,
image: String,
description: String,
cost: Number,
createdAt: { type: Date, default: Date.now },
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
const Canyon = mongoose.model("Canyon", canyonSchema);
module.exports = Canyon;
const User = mongoose.model('User', userSchema);
module.exports = User
Here is the logic that is supposed to save the information to mongo. When I run, I get a "._id undefined". Any help.
const User = require('../models/user');
const Canyon = require('../models/Canyon');
router.post("/add", , function(req, res){
if(req.body.canyon &&
rea.body.image &&
req.body.description){
const newCanyon = {
canyon: req.body.canyon,
image: req.body.image,
description: req.body.description,
author: {
id: req.user._id,
}, username: req.user.username
};
Canyon.create(newCanyon, function(error, canyon){
if(error){
return next(error)
} else {
req.session.userId = user._id;
return res.redirect('/profile')
}
});
} else {
const err = new Error('All fields required.');
err.status = 400;
return next(err);
}
});
In your model schema, instead of
const canyonSchema = new Schema({
canyon: String,
image: String,
description: String,
cost: Number,
createdAt: { type: Date, default: Date.now },
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
Make the author itself the reference:
const canyonSchema = new Schema({
canyon: String,
image: String,
description: String,
cost: Number,
createdAt: { type: Date, default: Date.now },
author: { type: mongoose.Schema.ObjectId, ref: 'User', index: true },
});
To create a canyon object,
const newCanyon = {
canyon: req.body.canyon,
image: req.body.image,
description: req.body.description,
author: req.user._id
};
To get the user information embedded in the canyon object when query on canyons, just populate the author in the query,
Canyon.findById(id).populate('author').exec()

Mongoose not saving changes to a document

I'm sorry if this might be a duplicate question but I'm quite having a hard time understanding Mongoose. I am working on a Node.js project that implements Mongoose and MongoDB. What I want to accomplish is to modify and save some users' data through a call from a specific endpoint.
Mongoose Schema looks like this
var UserSchema = new Schema({
isAdmin: {type: Boolean, default: false},
name: String,
surname: String,
nickname: { type: String },
email: { type: String, lowercase: true, required: true, trim: true, unique: true, dropDubs: true },
password: { type: String, required: true },
salt: { type: String },
verified: { type: Boolean, default: false },
bio: {
type: { type: String, enum: [0,1] }, // 0='Appassionato', 1='Giocatore'
birthday: String,
height: Number,
number: Number,
role: { type: String, enum: [0,1,2,3] }, // 0='Playmaker', 1='Ala', 2='Guardia', 3='Centro'
team: String,
city: String,
aboutMe: String,
},
newsletter: {type: Boolean, default: false},
lastCheckin: {type: mongoose.Schema.Types.ObjectId, ref: 'Checkin'},
follows: [{type: mongoose.Schema.Types.ObjectId, ref: 'Structure'}],
score: { type: Number, default: 0 },
profilePicture: String,
lastLogin: {type: Date},
facebook: {
id: String,
accessToken: String,
profileImage : String
}
}, {
collection: 'users',
retainKeyOrder: true,
timestamps: true,
}).plugin(mongoosePaginate);
Following is the code for when the endpoint gets interrogated
exports.updateUser = (req,res) => {
var userId = req.params.userId;
var updates = req.body;
User.findOneAndUpdate({_id: userId}, {$set: updates}, (err, saved) => {
if (!err) {
console.log("Ritorno questo: " + saved);
return res.status(202).json(saved);
} else {
return res.status(500).json(saved);
}
});
};
As far as I understood, the method findOneAndUpdate exposed by Mongoose should find the document I'm looking for and then modify it and save it. This doesn't happen though.
Through PostMan I'm sending this JSON
{"bio.aboutMe":"Hello this is just a brief description about me"}
But PostMan is responding with the non-modified object. What am I missing here?
What you need to do is to add {new:true}, it give you back the updated document.
In the documentation :
If we do need the document returned in our application there is
another, often better, option:
> Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true },
> function (err, tank) { if (err) return handleError(err);
> res.send(tank); });
This is something I don't really like as there is another option if we don't want to have the document → update
So what you need to do is :
User.findOneAndUpdate({_id: userId}, {$set: updates}, {new:true}.....

Mongodb mongoose node js schema relation

hello i am new on mongodb and node js i have a question
here is my product schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const categorySchema = require('./category');
const ProductSchema = new Schema({
country: {
type: String,
required: [true, "country can't be null"]
},
city: {
type: String,
default: ""
},
name: {
type: String,
required: [true, "name can't be null"]
},
measureValue: {
type: Number,
default: 0
},
minPrice: {
type:Number,
required: [true, "minPrice can't be null"],
min: [1,"minPrice must be at least 1"]
},
maxPrice: {
type:Number,
required: [true, "maxPrice can't be null"],
min: [1,"maxPrice must be at least 1"]
},
photoUrl: {
type:String,
default: ""
},
explanation: {
type: String,
default: ""
},
category: [categorySchema.schema],
userID: {
type: String,
required: [true,"userid cant be null"]
},
isActive: {
type: Boolean,
default: true
},
createdDate: {
type: Date,
default: Date.now
},
deletedDate: {
type:Date
}
})
and here is my category schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CategorySchema = new Schema({
name: {
type: String,
required: [true, "name can't be null"]
},
createdDate: {
type: Date,
default: Date.now
},
deletedDate: {
type:Date
}
})
i need to do this;
every product data must be have category
if one day,one category's name changed then every product that relation with that category must changed
i am trying to set category id to product schema and when i fetch the data it must be comes every product with category name as json
i am really confused if you help me i'd be really thankful
You can set up your category as :
category: {
type: mongoose.Schema.Types.ObjectId,
ref: 'category' //your model name
}
You can wrap it into an array and name it categories if you want multiple categories.
Then when you get the data, you will have to execute new Product().populate('category') to get retrieve the category data instead of just returning the category ObjectId.

Categories