Find user and insert products in that user - node.js

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.

Related

Mongoose Could not find path "${filterPath}" in schema by updating a subdocument

In this Items object:
{
"items": [
{
"_id": "63a48f12a9731cfd8a64b0b1",
"item_name": "addidas shoes",
"__v": 0,
"rating": [
{
"_id": "63a48fd51fb70775d216eb87",
"rate": 1,
"user_id": "6398a1a157d6146413b23b43"
}
]
}
]
}
I'm trying to update the rating property if a user_id inside of it already exists, else, add a new object into it.
const addRating = async (req, res) => {
const { rate, user_id, item_id } = req.body;
// item_id = 63a48f12a9731cfd8a64b0b1 user_id = 6398a1a157d6146413b23b43 rate = 6
// Adding ratings to the selected item
const test = await itemDB.item.updateOne(
{ _id: item_id, rating: { user_id: user_id } },
{ $push: { "items.rating.$[i].rate": rate } },
{ arrayFilters: [{ "i.user_id": user_id }], upsert: true }
);
console.log(test);
res.json({ message: "success" });
};
I wanted to change something in the rating property so I set the filter as above but it gives me this error when hitting the endpoint:
\node_modules\mongoose\lib\helpers\update\castArrayFilters.js:74
throw new Error(`Could not find path "${filterPath}" in schema`);
^
Error: Could not find path "items.rating.0.user_id" in schema
This is my Items Schema:
const mongoose = require("mongoose");
const RateSchema = mongoose.Schema({
rate: {
type: Number,
required: true,
},
user_id: {
type: mongoose.ObjectId,
},
item_id: {
type: mongoose.ObjectId,
},
});
const ItemSchema = mongoose.Schema({
item_name: {
type: String,
required: true,
},
rating: {
type: [RateSchema],
},
});
module.exports = mongoose.model("Items", ItemSchema);
It looks like it is not noticing that items is also an array when applying the array filter to rating.
Try using the all-positional operator like:
{ $push: { "items.$[].rating.$[i].rate": rate } }

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 } } } } );

Find if User Exist in array mongodb and Nodejs

I have this opportunity model that has this field likes, which is an array of users. How do I check first if the user exist already in that array and if they do I pull them and if they don't I push them back I am building a like creteria for posts
Here is my opportunity model
const mongoose = require("mongoose");
const OpportunityModel = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
content: {
type: String,
required: true,
trim: true,
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
image: [
{
type: Object,
},
],
share_with_thoughts: {
type: mongoose.Schema.Types.ObjectId,
ref: "Shares",
},
comments: {
type: mongoose.Schema.Types.ObjectId,
ref: "Comment",
},
is_opportunity_applied: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
});
const Opportunity = mongoose.model("Opportunity", OpportunityModel);
module.exports = Opportunity;
What I tried doing but did not work
const likeOrUnlikeOpportunity = expressAsyncHandler(async (req, res) => {
let userId = req.user._id;
let opportunityId = req.params.opportunityId;
let isUserExist = await Opportunity.find({
$and: [{ _id: opportunityId }, { likes: { $elemMatch: { $eq: userId } } }],
}).populate("user", "user_id user_name");
if (isUserExist.length > 0) {
const unliked = await Opportunity.findByIdAndUpdate(
opportunityId,
{
$pull: { users: userId },
},
{ new: true }
).populate("user", "user_id user_name");
if (!unliked) {
res.status(500).send({ ErrMessaage: "an error occured" });
} else {
res.status(200).json(unliked);
}
} else {
const added = await Opportunity.findByIdAndUpdate(
opportunityId,
{
$push: { users: userId },
},
{ new: true }
).populate("user", "user_id user_name");
if (!added) {
res.status(500).send({ ErrMessaage: "an error occured" });
} else {
res.status(200).json(added);
}
}
});
In this case, the action should be dynamic [like | unlike] function, You don't have to chain the function since the like and unlike function/api can't be called at the same time.
Make Your Query Conditional;
Just make sure you have a way to identify between like and unlike.
const {like, postId} = req.body;
let query = {[`${'$' + (like ? 'push' : 'pull')}`]: {likes: userId}};
//assumes that you have the post id
// you can decide not to wait for it to update, just to be sure it did update
await post.findByIdAndUpdate(postId, query).exec()
I hope this helps.

Why this code is creating two similar object in mongodb?

Node js
The method used to post the comment data
const { type, movieId, userId, review, timestamp } = req.body;
const movie = await Movie.findOneAndUpdate(
{ movieId: movieId, type: type },
{
$push: {
movieReview: { ... },
},
},
{ upsert: true, new: true },
(err, info) => {
...
}
);
Reactjs
The method used to submit the comment
const submit_comment = async () => {
....
const file = {
movieId: id,
type: type,
userId: userInfo._id,
comment: comment,
};
if (!commentFlag) {
const { data } = await axios.post("/api/movie/add-comment", file, config);
...
};
Mongoose Schema
const movieSchema = new mongoose.Schema({
movieId: String,
type: String,
...
comment: [{ type: mongoose.Schema.Types.ObjectId, ref: "Comment" }],
});
After I run my submit function it posts two objects with the same object _id in mongoDB

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

Resources