NodeJS Mongoose updateOne giving no match every time - node.js

I am trying to update a document in mongo with mongoose using updateOne method:
const updateResult = await UserModel.updateOne({
_id: mongoose.Types.ObjectId(userId)
}, {
$set: {
a: 'B'
}
})
userId contains a string of the ID of the user.
I have tried using the following
1. { _id: userId }
2. { email: theEmailOfTheUser }
But still, the updateResult is
n:0, nModified:0, ok:0
So I think it's must be something with the method itself and not in my query.
Also, when I'm trying to find the user using the query below, it can find it:
const user = await UserModel.find({
_id: userId
});
//user is found

Actually mongoose takes care of the $set and you do not have to add it. just:
const updateResult = await UserModel.updateOne({
_id: userId
}, {
a: 'B'
})
but the better solution would to just use findByIdAndUpdate():
const updateResult = await UserModel.findByIdAndUpdate(userId, {
a: 'B'
})

Related

How to remove a certain position from an array of objects that matches a value in Mongoose?

Is the first time I am working with backend (Mongoose, express, nodeJs). I have a collection of users in MongoDB.
I am sending the favoriteId from frontend and getting it in the backend. I want to delete the position of the array that matches with the favorite Id I am passing to the function.
I have tried several ways to remove the favorite using the $pull operator and the favoriteId but none work. So I don't know how to do it.
I would appreciate if someone could help me.
This is structure in MongoDB:
_id: new ObjectId("63"),
username: 'test1',
email: 'test1#gmail.com',
favorites: [
{
id: '25',
version: 'version3',
team: 'team1',
},
{
id: '27',
version: 'version2',
team: 'team4',
}```
This is my controller function:
```export const removeFavorite = async (req, res) => {
//Here I have the user Id 63
const userId = req.params.userId;
//here I have the favorite Id I Want to remove : 25
const favoriteId = req.body.params.id;
// Here I select the user in the collection
const deleteFavorite = await User.findOne({ _id: userId });
// Here I want to remove the favorite that matches with favoriteId (25)
res.status(200).json('ok');
};```
Try this:
User.update({ _id: userId }, { $pull: { 'favorites': { 'id': favoriteId } } });

how to loop over an array and get data for each element? - with mongoose & node.js

I am trying to build a social network. I have a collection of "connections"/"friend requests".
the schema is as follows:
{
senderId: { type: String },
receiverId: { type: String },
approved: { type: Boolean },
},
when the person didn't approve the connection yet, the connection is marked with "pending".
when the user enter to the website, i get all the pending connections people sent him, with this command:
const requestsPending = await Connection.find({
receiverId: userId,
approved: false,
});
the thing is, in the backend, I want to get the details of the people who send the friend requests (so I can show their name+picture).
I want to loop over the pending requests array, and get the extra data of the user who sent the request.
await User.findById(requestsPending[0][senderId]);
any idea how to do it for each element? what's the best approach?
or any idea how to do it more efficiently?
thank you.
this seems to work:
var requestsPendingWithUsersData = await Promise.all(
requestsPending.map(async (item) => {
const userData = await User.findById(item.senderId);
return {
item,
senderData: { picture: userData.picture, name: userData.username },
};
})
);
await User.find({
'senderId': { $in: [
101,102,103,...
]}
})
You can try something like the above, where you pass an array of senderID to $in. The $in clause is similar to like operator in SQL.
If the senderId is an ObjectId, pass them as ObjectID types
await User.find({
'senderId': { $in: [
mongoose.Types.ObjectId(<senderID>),
]}
})
If the mongo Document is heavier/larger, use lean() at the end of the query. Enabling the lean option tells Mongoose to skip instantiating a full Mongoose document.
await User.find({
'senderId': { $in: [
101,102,103,...
]}
}).lean()

How to reuse already exec query mongodb mongoose in nodejs

is that posible to reuse already exec mongodb/mongoose query in nodejs?
for example i create query like this to check if user exist or not:
const inviter = await User.findOne({ _id: req.userData._id }).exec()
// there's bunch of code bellow here before update the user data
basically if i want to update the data, then i have to write the same code again and add update function like this:
User.findOneAndUpdate({ _id: req.userData._id }, { $push: { invited: recipient.value } }, { useFindAndModify: false })
is that posible to continue the first query and add short query to update based on result of the first query, for example like this:
inviter.update({ $push: { invited: recipient.value }).exec()
i know this code is not work..
you can use this approach :
User.findOne({ _id: req.userData._id }).exec((err, result) => {
if(result)
{
result.invited = recipient.value;
result.save((err) => {
if (err) // do something
});
}
})
}

mongoose filter by multiple conditions and execute to update data

I am wondering what would be the best approach to make schema functions using mongoose. I have never used this so the way I think is somewhat limited, same goes for looking for docs, without knowing what's available, is not very efficient.
Through docs I found that either using findOneAndUpdate might solve the problem; but there are some constraints.
Here is the code I am planning to run:
models/Bookmark.js
const mongoose = require('mongoose')
const bookmarkItemSchema = new mongoose.Schema({
restaurantId: String,
cachedAttr: {
name: String,
latitude: Number,
longitude: Number,
},
})
const bookmarkListSchema = new mongoose.Schema({
listName: String,
items: [bookmarkItemSchema],
})
const bookmarkSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
lists: [bookmarkListSchema],
})
// const add = (lists, userId) => {
// let bookmark = Bookmark.findOne({userId})
// bookmark.lists.listName === lists.listName //current, new
// ? bookmark.lists.items.push(lists.items)
// : bookmark.lists.push(lists)
// return bookmark
// }
mongoose.model('Bookmark', bookmarkSchema)
Routes/bookmark.js
router.post('/bookmarks', async (req, res) => {
const {lists} = req.body
console.log(lists)
if (!lists) {
return res.status(422).send({error: 'You must provide lists'})
}
let bookmark = Bookmark.findOne({"userId": req.user._id})
if (bookmark.lists.listName === lists.listName){
let item = lists.items
bookmark.lists.items.push(item)
await bookmark.save()
res.send(bookmark)
}
try {
// const bookmark = Bookmark.add(lists, req.user._id, obj)
// await bookmark.save()
// res.send(bookmark)
let bookmark = Bookmark.findOne({"userId": req.user._id})
if (bookmark.lists.listName === lists.listName){ // THIS IS UNDEFINED. How to get this object?
let item = lists.items
bookmark.lists.items.push(item)
await bookmark.save()
res.send(bookmark)
}
} catch (e) {
res.status(422).send({error: e.message})
}
})
The req.body looks like this:
{
"lists": {
"listName": "My Saved List",
"items": {
"restaurantId": "abcdefg",
"cachedAttr": {
"name": "abcdefg",
"latitude": 200,
"longitude": 200
}
}
}
}
Basically what I commented out in the models/Bookmark.js file is what I would really like to do.
If the userId's list name already exists, then I would like to just add an item to the list.
Otherwise, I would like to add a new list to the object.
What is the best approach for doing this? Is there a straight forward mongoose api that I could use for this problem? or do I need to make two separated function that would handle each case and make that as schema methods and handle it in the routes file?

How to set specific property in mongo document incremently using $inc? If property does not exist in document

I am running a utility to update all documents. I don't know what am I doing wrong in the code. Here is my code.
let userId = userIds.pop();
let allMembers = await Member.find({ userId: userId }).lean();
allMembers = allMembers.map((obj) => obj._id);
await Member.updateMany({ _id: { $in: allMembers } }, { $inc: { index: 1 } });
the index does not exist in my document.
Looking for a solution!

Resources