Insert Value in Object Aarray (Mongoose) - node.js

I cant update a value in a array object with an ObjectId.
I think it fails when comparing the id of the event Id of the User model that is an ObjectId with the id per parameter that is a string
Model:
tareas: [{
eventId: {
type: [Schema.Types.OjectId],
ref: 'Event'
},
tareasDelUsuario: {
type: []
}
}],
I tried in controller:
await User.findOneAndUpdate(
{
_id: id,
'tareas.eventId': eventId
},
{
$push: {
'tareas.$.tareasDelUsuario': tarea
}
});
and:
await User.findOneAndUpdate(
{ _id: id },
{
"$set": { ['tareas.$[el].tareasDelUsuario']: tarea }
},
{
"arrayFilters": [{ 'el.eventId': eventId}]
});

Related

Delete a single document from nested document array by its id

I have this model for a user, the user can also be a driver and the driver have an array of cars. I want to delete a specific car from all the cars of drivers, but my query deletes all the cars.
This is the schema:
const UserSchema = new mongoose.Schema({
name: {
type: String,
},
driverData: {
ExperienceLevel: {
type: String,
},
rides: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "ride.model",
},
],
cars: [
{
id: {
type: mongoose.Schema.Types.ObjectId,
},
licensePlateNumber: {
type: String,
},
},
],
},
});
Code I am using to pull a car by id.
user = await User.findByIdAndUpdate(
{ _id: userId },
{ driverData: { cars: { $pull: { id: carId } } } }
);
Only a single car object and a single car id is left after making this query, all other data is removed. How to only remove only a single car.
Your syntax is incorrect. Try this:
user = await User.findByIdAndUpdate( { _id: userId }, { $pull: { driverData: { cars: { $elemMatch: { id: carId } } } } );

MongoDB array of objects update

I'm trying to update array of user information objects in mongoose.
I've stored the user core information in the login process, I want to update some of user information when user tries to make an order.
Here is the code for the model
const mongoose = require('mongoose');
const { ObjectId } = mongoose.Schema;
const userSchema = new mongoose.Schema(
{
name: String,
email: {
type: String,
required: true,
index: true,
},
role: {
type: String,
default: 'subscriber',
},
info: [
{ country: String },
{ city: String },
{ address: String },
{ phone: String },
{ birthdate: Date },
{ gender: { type: String, enum: ['Male', 'Female'] } },
],
// wishlist: [{ type: ObjectId, ref: "Product" }],
},
{ timestamps: true }
);
module.exports = mongoose.model('User', userSchema);
In my controller I'm getting the data from front-end react app as JSON format, I want to push some data to info which is an array of objects in the users model above.
exports.createOrder = async (req, res) => {
// Here I constract the data
const { plan, service, fullName, country, city, address } = req.body.order;
const { user_id } = req.body;
// This the method I tried
try {
const user = await User.updateOne(
{
_id: user_id,
},
{
$set: {
'info.$.country': country,
'info.$.city': city,
'info.$.address': address,
},
},
{ new: true }
);
if (user) {
console.log('USER UPDATED', user);
res.json(user);
} else {
res.json((err) => {
console.log(err);
});
}
const newOrder = await new Order({
orderPlan: plan,
orderService: service,
orderUser: user_id,
}).save();
console.log(newOrder);
console.log(req.body);
} catch (error) {
console.log(error);
}
};
I tired other solutions like
const user = await User.updateOne(
{
_id: user_id,
info: { $elemMatch: { country, city, address } },
},
{ new: true }
);
So do I need to reformat my model or there is a way to update this array of objects?
Option 1
Use $[]
db.collection.update(
{},
{ $set: { "info.$[i].country": "a1" }} ,
{ arrayFilters: [ { "i.country": "a" } ] }
)
Demo - https://mongoplayground.net/p/UMxdpyiKpa9
Option 2
if you know the index
Demo - https://mongoplayground.net/p/41S7qs6cYPT
db.collection.update({},
{
$set: {
"info.0.country": "a1",
"info.1.city": "b1",
"info.2.address": "c1",
"info.3.phone": "d1"
}
})
Suggestions -
Change info schema to object instead of an array

Delete an object from an array in Express Mongoose

{
"_id": "608c3d353f94ae40aff1dec4",
"userId": "608425c08a3f8db8845bee84",
"experiences": [
{
"designation": "Manager",
"_id": "609197056bd0ea09eee9429c"
},
{
"designation": "Asst. Manager",
"_id": "608c530de8ade5221b0e6d4e"
},
{
"designation": "Sr. Manager",
"_id": "608c534be8ade5221b0e6d4f"
},
]
}
I want to delete object in array with id 608c530de8ade5221b0e6d4e, here is my code but that gives me error.
This is the controller:
const userId = req.userData.userId;
const id = req.params.id;
Experience.findOneAndUpdate({ userId: userId }, { $pull: { 'experiences': { '_id': id } }}, { multi:true }, function(err, obj) {
// //do something here
});
This is model:
const newExpSchema = new mongoose.Schema({
designation: { type: String, default: ""},
});
const experienceSchema = new mongoose.Schema({
userId: { type: String, required: true },
experiences: [newExpSchema],
});
export default model("experience", experienceSchema);
I am getting below error on { $pull: { 'experiences': { '_id': id } }}
Error:
No overload matches this call.
Overload 1 of 3 .........
.......
The expected type comes from property '$pull' which is declared here on type 'UpdateQuery<Document<any, {}>>'
Can you try this:
Folder.findOneAndUpdate({
"_id": "608c3d353f94ae40aff1dec4"
},
{
$pull: {
"experiences": {
"_id": "608c530de8ade5221b0e6d4e"
}
}
},
{
"multi": false
})
Here is a working example: https://mongoplayground.net/p/YtNGBTr52U9

Find user and insert products in that user

I wand to create document inside the user by using his object ID.
This is my schema
const productsSchema = mongoose.Schema({
product_name: {
type: String,
},
product_price: {
type: Number,
},
});
const sellersSchema = mongoose.Schema({
user_firstname: {
type: String
},
user_lastname: {
type: String
},
user_mobile: {
type: Number
},
products: [productsSchema]
});
And this is my code
module.exports.uploadProducts = function(productDetails, callback) {
var id = productDetails.userId;
db.findOneAndUpdate({ "_id": ObjectId(id) }, { $set: { products:
productDetails } }, { new: true }, callback)
}
But in this case products are updating in the particular user but I want to insert document inside that user based on ID.
Use $push:
module.exports.uploadProducts = function(productDetails, callback) {
var id = productDetails.userId;
db.update({ "_id": ObjectId(id) }, { $push: { products:
productDetails } }, callback)
}
Hope this helps you.

Mongodb - aggregate by embedded document id overwrite the outer document _id

I have this kind of 'comment' model:
{ _id: <comment-id>,
user: {
id: { type: Schema.ObjectId, ref: 'User', required: true },
name: String
},
sharedToUsers: [{ type: Schema.ObjectId, ref: 'User' }],
repliedToUsers: [{ type: Schema.ObjectId, ref: 'User' }],
}
And I want to query for all comments which pass the following conditions:
sharedToUsers array is empty
repliedToUsers array is empty
But also, I want the result to contain only 1 comment (the latest comment) per user by the user id.
I've tried to create this aggregate (Node.js, mongoose):
Comment.aggregate(
{ $match: { "sharedToUsers": [], "repliedToUsers": [] } },
{
$group: {
_id: "$user.id",
user: { $first: "$user" },
}
},
function (err, result) {
console.log(result);
if (!err) {
res.send(result);
} else {
res.status(500).send({err: err});
}
});
It is actually working, but the serious problem is that the results comments _id field is been overwritten by the nested user _id.
How can I keep the aggregate working but not to overwrite the original comment _id field?
Thanks
Ok, I have a solution.
All I wanted is to group by _id but to return the result documents with their _id field (which is been overwritten when using $group operator).
What I did is like wdberkley said, I've added comment_id : { "$first" : "$_id" } but then I wanted not to return the comment_id field (because it doesn't fit my model) so I've created a $project which put the comment_id in the regular _id field.
This is basically how it looks:
Comment.aggregate(
{
$match: {
"sharedToUsers": [], "repliedToUsers": []
}
},
{
$group: {
comment_id: { $last: "$_id" },
_id: "$user.id",
content: { $last: "$content" },
urlId: { $last: "$urlId" },
user: { $last: "$user" }
}
},
{
$project: {
_id: "$comment_id",
content: "$content",
urlId: "$urlId",
user: "$user"
}
},
{ $skip: parsedFromIndex },
{ $limit: (parsedNumOfComments - parsedFromIndex) },
function (err, result) {
console.log(result);
if (!err) {
Comment.populate(result, { path: "urlId"}, function(err, comments) {
if (!err) {
res.send(comments);
} else {
res.status(500).send({err: err});
}
});
} else {
res.status(500).send({err: err});
}
});
thanks wdbkerkley!

Resources