Nodejs, Moongos find subdocument - node.js

I have this query ( mongoose)
user = {email:'my#email.com};
return this.company.get().findOne({
name: companyName,
users: { $elemMatch: user }
}).then((res: ICompany) => {
console.log(res.users);
}
The query is working.
The problem is that I was expecting one user in res.users (the one that match the $elemMatch), instead it returns all the users and to select my User I have to do a for-loop over all the users.
Is it possible to modify my query in the way that the res.users is populated with the user that match the email?
Thank you

Use of projection, here the documentation of mongodb 3.6
return this.company.get().findOne({
name: companyName,
users: { $elemMatch: user }
}, {
'users.$': 1,
}).then((res: ICompany) => {
console.log(res.users);
});

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

Query MongoDB using an object and array of ids

In searching through MongoDB data I've been able to query a collection based on whatever fields the user provides by adding any non-null field to a query object, which so far has covered all of my bases. But I've run into an issue with needing to add to it. Basically doing this for 10+ fields:
let query = {};
let weekNumber = null;
if (req.params.weekNumber !== 'noDataSent'){
weekNumber = req.params.weekNumber;
query.weekNumber = weekNumber;
}
...
Ticket.find(query)...
I've got two collections, User and Ticket. The Ticket objects contain an objectId ref to a User object. Since I can't query the Tickets by a users name due to the ref, I'm finding all users based on a provided name and then pulling out their _id to then add to the query object. In this case, if nothing else is specified I would like the result to only return the tickets that match any of the user _ids, and if there are other fields to work the same, to match everything else and find the tickets with the user ids.
I've tried using $or and $in, but unless I'm doing something wrong, I can't figure out how to make this work right.
Doing this returns an error, and I'm not even sure how to go about using $or in this case.
let users = [];
User.find( { $or: [ { firstname: requestor }, { lastname: requestor } ] } ).exec((err, user) => {
if (err){ return res.status.json({err: "No user(s) found"}); }
user.forEach((e) => {
users.push(new ObjectId(e._id));
});
});
Ticket.find(query, { requestor: { $in: users } } )
How can I match all of the fields in my query object and find all tickets with the user(s) _ids with this setup?
Edit:
I've tried doing this to get it to search through both, and this does search through the users correctly and brings back the tickets tied to them, it is ignoring everything in the query object.
Ticket.find({
$and:
[
{ query },
{requestor:
{ $in: users.map(doc => new ObjectId(doc._id))
}
}
]
})
You are running Ticket.find() outside of the callback of User.find(). While this is valid code, both of these queries are effectively queued up to go concurrently, with the the Ticket query utilizing the array of users - which the Users query has yet to populate.
In order to use the result of the Users query, you must put the next bit of code in that callback which can only be called after the query is complete:
User.find({
$or: [
{ firstname: requestor },
{ lastname: requestor }
]
}).exec((err, users) => {
if (err) return res.status.json({ err: "No user(s) found" });
Ticket.find({
requestor: {
$in: users.map(doc => new ObjectId(doc._id))
}
}).exec((err, tickets) => {
if (err) return res.status.json({ err: "No ticket(s) found" });
// do something with 'tickets'
tickets.forEach(doc => console.log(doc));
});
});
To solve my original question of how to search through the tickets using the query object I built up as well as use $in to find the tickets associated with the returned users, I came up with this solution that seems to work nicely.
query.requestor = { $in: users.map(doc => new ObjectId(doc._id)) };
Set the query. to the field I want to search through, in this case the requestor. That way I can simply do what I've been doing thus far and do a plain Ticket.find(query)

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()

add item to array if it doesn't exist mongodb

I'm running a simple application with mongoDB + nodejs, I'm trying to achieve the following:
The unit belongs to a company, the classroom belongs to a unit and the user belongs to a classroom.
In certain moment, I want to add the user to another unit or/and classroom, then he'll belong to 2 or more units/classrooms.
My form will sent only one unit/classroom per time, in this case, I want to add it to the user model unit:[string] and classroom:[string] only if he doesn't previously belong to it. So I need to check if the arrays already have the sent data, if don't, add to it.
Mongo has the $addToSet property, and the $ne to do it, but I can't seem to make it work.
Here's my code:
User.findById(req.body._id)
.select("-__v")
.exec((err: Error, user: any) => {
if (err) {
// display error
}
if (!user) {
// display error
}
user.update({
unit: {
$ne: user.unit
},
classroom: {
$ne: user.classroom
}
}, {
$addToSet: {
unit: req.body.unit,
classroom: req.body.classroom
}
}).exec((err: Error) => {
if (err) {
// Display error
}
res.status(200).json({
status: "OK",
response: response,
})
return
})
It belongs to "Academy one" and the classroom id reference, I will add him to another unit like "Academy 2" and add another classroom reference, but if I add him to another classroom of "Academy One", I don't want a duplicate item in it's unit array.
When I post the following through postman, it gives me the error:
{
"_id":"5d8ba151248ecb4df8803657", // user id
"unit":"Test", // another unit
"classroom":"5d8a709f44f55e4a785e2c50" // another classroom
}
Response:
{
"status": "NOK",
"response": "Cast to [string] failed for value \"[{\"$ne\":[\"Academy One\"]}]\" at path \"unit\"" }
What am I missing?
Actually, I didn't needed the $ne operator, I just needed to use the $addToSet directly
user.updateOne({
$addToSet: { unit: req.body.unit, classroom: req.body.classroom }
}).exec((err: Error) => {
Thanks!
You need to use $nin instead of $ne, https://docs.mongodb.com/manual/reference/operator/query/nin/
unit: {$nin: [user.unit]}

How to get all users except select user from mongodb using mongoose

I'm trying to get the users from the mongo database using mongoose.
If i select a user i want to eliminate that user records and get all the remaining users from database.
how can i do that?
you can try to use the query below:-
UsersModel.find({ email: { $ne: 'testemail#email.com' } })
Let me know if it helps. Thanks
Here User is the user model. we will get all users except the current user
const users = User.find({ _id: { $ne: user._id } })
UsersModel.find({ email: { $ne: 'testemail#email.com' } })
for more follow this url
https://docs.mongodb.com/manual/reference/operator/query/ne/
Well, if you want to exclude just one user, you can use
db.collection.find( { name: { $ne: "name" } } )
And if you want to exclude more than one records. May be more than one selected records. This is the way to go
db.collection.find( { name: { $nin: ["name1", "name22"] } } )

Resources