How to use pop and push in one query with mongoose? - javascript

Is it possible to do this two "operation" in one query
const deleteUser = await BOQ.findOneAndUpdate({_id:req.params.id}, { $pop: { user: 1 }});
const assignUser = await BOQ.findOneAndUpdate({_id:req.params.id}, {$push:{user: req.params.userId}})
If it possible can anyone tell me how ?
I try
const deleteUser = await BOQ.findOneAndUpdate({_id:req.params.id}, { $pop: { user: 1 }},
{$push: {user: req.params.userId}});
But it won`t work

const deleteUser = await BOQ.findOneAndUpdate(
{ _id: req.params.id },
{
$pop: { user: 1 },
$push: { user: req.params.userId }
}
);
The second paramter is a document of update operators. You can refer the documentation for more detail on the parameters.

Related

mongodb edit array don't update it

I'm trying to edit the collection of users where their purchase date has expired but when I'm saving, user.role have been updated but purchaseHistory don't have been updated.
Here is the function
async function checkExpiredPurchase() {
const users = await User.find({
"purchaseHistory.expdate": { $exists: true, $lte: new Date() }
});
for(const user of users) {
let purchases = await user.purchaseHistory.map(purchase => {
if(purchase.expdate && purchase.expdate <= new Date()) {
purchase.expdate = null;
}
return purchase
});
user.role = "Utilisateur"
user.purchaseHistory = purchases
console.log(user.purchaseHistory) //here it return [{"date":"2022-12-12T20:53:48.467Z","item":"VIP","expdate":null,"methode":"PayPal"}] which is what I want
user.save(function(err, resolve) {
if (err)
console.log('db error', err)
// saved!
});
}
}
And when I check on MongoDB Compass (after refreshing ofc), I see that the role have been updated but not the array with purchaseHistory since expdate is still egal to a date and not to "null"
And I've also tried with this code for update
User.updateOne(
{ _id: user.id },
{ $set: { purchaseHistory: purchases }, $set: { role: "Utilisateur" } },
).then(() => { console.log('should be good')})
But as well as the other one, role update, not purchaseHistory
There was never an error in the console. Thank you in advance for any answers you can bring me
I was not able to reproduce the problem, it worked here just fine:
var mongoose = require('mongoose');
mongoose.set('strictQuery', true);
(async () => {
await mongoose.connect("mongodb://user:password#0.0.0.0:50000", { dbName: "somedb" });
const User = mongoose.model("user-test", {
purchaseHistory: [{ expdate: Date, item: String }],
role: String
});
await User.deleteMany({});
await User.insertMany([
{ role: "User", purchaseHistory: [{ expdate: "1800-01-01", item: "VIP" }], },
{ role: "User 2", purchaseHistory: [{ expdate: "2050-01-01", item: "VIP" }], }
]);
const users = await User.find({
"purchaseHistory.expdate": { $exists: true, $lte: new Date() }
});
console.log("\r\nDOCUMENT BEFORE SAVE:\r\n\r\n", users[0]);
for (const user of users) {
user.purchaseHistory.forEach(purchase => {
if (purchase.expdate && purchase.expdate <= new Date()) {
purchase.expdate = null;
}
});
user.role = "Utilisateur"
console.log("\r\nDOCUMENT AFTER SAVE:\r\n\r\n", await user.save());
}
})();

Prisma find many and count in one request

I have a pagination in my category service, and I have to return obj with total count of categories and data
But there's can be some parameters. As example, I should return categories that was created by certain user:
async findAll(
{ onlyParents }: ParamsCategoryDto,
user: ITokenPayload | undefined,
): Promise<IFilterRes> {
const categories = await this.prisma.category.findMany({
where: {
user_id: user?.id,
},
});
return {
pagination: {
total: this.prisma.category.count({
where: { // <- duplicate
user_id: user?.id,
},
}),
},
data: categories,
};
}
I should duplicate where in both query. Which is not very nice. Is there any option to do it in one request.
P.S. I can make some var for where, but in this way I lose typification, which I also don't like.
This is my example code to acheive it with a single transaction, no duplicate code and not losing type autocomplete
import { Prisma } from '#prisma/client';
import { PrismaClient } from '#prisma/client'
const prisma = new PrismaClient()
const findAll = async (userId: String) => {
const query: Prisma.categoriesFindManyArgs = {
where: {
user_id: userId,
}
};
const [categories, count] = prisma.$transaction([
prisma.categories.findMany(query),
prisma.categories.count({ where: query.where })
]);
return {
pagination: {
total: count
},
data: categories
};
};

Why could the findOrCreate plugin create several documents at once?

I'm currently working on a MERN application with following/follower function for the users. I decided to create separate schemas for following and follower relationships detached from user schema.
Follower schema
const mongoose = require('mongoose');
const findOrCreate = require('mongoose-findorcreate');
const ObjectId = mongoose.Schema.Types.ObjectId;
const followerSchema = mongoose.Schema({
userId: {
type: ObjectId,
ref: 'User'
},
follower: {
type: [ObjectId],
ref: 'User'
}
});
followerSchema.plugin(findOrCreate);
const Follower = mongoose.model('Follower', followerSchema);
module.exports = { followerSchema, Follower };
Following schema
const mongoose = require('mongoose');
const findOrCreate = require('mongoose-findorcreate');
const ObjectId = mongoose.Schema.Types.ObjectId;
const followingSchema = mongoose.Schema({
userId: {
type: ObjectId,
ref: 'User'
},
following: {
type: [ObjectId],
ref: 'User'
}
});
followingSchema.plugin(findOrCreate);
const Following = mongoose.model('Following', followingSchema);
module.exports = { followingSchema, Following };
The problem however starts in my service where followings are created as supposed to. However, for followers mongoose create 6-8 documents at once with userIds that don't even exist in my db.
Here's the code of the followerService (it's the first function)
const { Follower } = require('../models/followerModel');
const { Following } = require('../models/followingModel');
const { User } = require('../models/userModel');
const mongoose = require('mongoose');
exports.changeFollowStatus = async (user, userId) => {
console.log({ userId: userId, user: user._id });
const newFollowing = await Following.findOrCreate({ userId: user._id }, (err, following, created) => {
console.log({following: following});
if (!err && !isFollowing(following, userId)) {
following.following.push(mongoose.Types.ObjectId(userId));
following.save();
User.findByIdAndUpdate(mongoose.Types.ObjectId(userId), {$inc: {follower: 1}});
} else {
const followingIndex = following.following.indexOf(mongoose.Types.ObjectId(userId));
following.following.splice(followingIndex, 1);
following.save();
User.findByIdAndUpdate(mongoose.Types.ObjectId(userId), { $inc: { follower: -1 } });
}
});
const newFollower = await Follower.findOrCreate({ userId: mongoose.Types.ObjectId(userId) }, (err, follower, created) => {
console.log({follower: follower});
if (!err && !isFollower(follower, user._id)) {
follower.follower.push(user._id);
follower.save();
User.findByIdAndUpdate(user._id, { $inc: { following: 1 } });
} else {
const followerIndex = follower.follower.indexOf(user._id);
follower.follower.splice(followerIndex, 1);
follower.save();
User.findByIdAndUpdate(user._id, { $inc: { following: -1 } });
}
});
};
exports.showFollowings = async (userId) => {
const followings = await Following.findOrCreate({ userId: mongoose.Types.ObjectId(userId) });
return followings.following;
};
exports.showFollowers = async (userId) => {
const followers = await Follower.findOrCreate({ userId: mongoose.Types.ObjectId(userId) });
return followers.follower;
};
const isFollowing = (newFollowing, userId) => {
return newFollowing.following.includes(mongoose.Types.ObjectId(userId));
};
const isFollower = (newFollower, userId) => {
return newFollower.follower.includes(userId);
}
Now, my following adding code and follower adding code look almost identical, but for some reason for followers, mongoose creates many more documents. The strange thing is that there is a follower document with the correct userId, but many other with random userIds get created which doesn't happen with followings which works as supposed to.
I also checked whether I pass the correct values and everything seems to be fine. But just for reference, here's the controller function from which I pass the values.
exports.changeFollowingStatus = async (req, res, next) => {
passport.authenticate('jwt', async (err, user, info) => {
if (err) {
console.error({ authError: err });
};
if (info !== undefined) {
console.error({ authError: info.message });
res.status(403).send(info.message);
} else {
console.log({params: req.params});
const userToFollow = req.params.id;
await FollowerService.changeFollowStatus(user, userToFollow);
res.status(200).send({ message: 'success' })
}
})(req, res, next);
};
Could anyone help me with this bug or at least navigate me towards the right direction? I can't seem to find solution to my problem. Thank you all in advance!

Multiple where with $or sequelize

I trying get all users by provided emails using where clause and $or in sequelize.
Where in sequelize
So i created query from my emails array for multiple where like this:
[ { email: 'email1#gmail.com' }, { email: 'email#gmail.com' } ]
Then i try to get it in many way for example like that:
const allExistedUsers = await User.findAll({
where: { $or: multileWhere }
});
According to answer in this post and doc it should work:
{ $and: [{"Key1": "Value1"}, {"Key2": "Value2"}] }
But it does not work. I can't figure out how to do it.
Your E-Mails as Array:
const mails = [ { email: 'email1#gmail.com' }, { email: 'email#gmail.com' } ];
const yourEmailsArray = mails.map( el => { return el.email; });
Then you can concat your E-Mails. Sequelize formats in:
WHERE (`User`.`email` = 'email1#gmail.com' OR `User`.`email` = 'email2#gmail.com')
const allExistedUsers = await User.findAll({
where: {
email: { [Op.or]: [].concat(yourEmailsArray)}
}
});
I did it using another approach from this post
here
const allExistedUsers = await User.findAll({
where: { email: { [Op.or]: usersEmailsToAssign } }
});
usersEmailsToAssign is a array with strings

I am New to nodejs and trying to update a category in categories table but it is not working

> I am trying to update a data using updateOne method but i am not able to debug it why it is not working ?
router.post('/edit-category/:slug', async (req,res) =>{
// res.send(req.body.id);
try{
const updatedPost = await Category.updateOne(
{ _id: req.body.id},
{
$set: { title: req.body.title },
$set: { slug: req.body.slug }
}
);
// updatedPost.update((error) => {if(error){console.log("hiiiiiiiii"+error)}});
res.send(updatedPost);
// console.log(updatedPost);
}catch(error){
console.log({message:error})
}
});
Two possibilities:
Check in DB whether the document is there in DB with req.body.id as _id
Try for the below code:
const ObjectId = require('mongodb').ObjectID;
const updatedPost = await Category.updateOne({ _id: ObjectId (req.body.id)}

Categories

Resources