mongodb multiple find by multiple conditions and one result nodejs - node.js

i have a collection for users transactions. i want to use a query by three id of users to get last transaction for each one. and i don't want to use a loop to do a query per user.
i used this:
const items = await db
.collection("transactions")
.find({ user: users[1] , user: users[2], user: users[3] })
.limit(3)
.sort({ $natural: -1 })
.toArray();
but it doesn't contain one result per condition because i know i'm doing it wrong.
i use:
const MongoClient = require("mongodb").MongoClient;
how should i do that?
thanks.

You probably need to do an aggregation using $group and $last.
https://docs.mongodb.com/manual/reference/operator/aggregation/group/#examples
db.collection("transactions").aggregate( [
{
$group: {
_id: user,
txnId: { $last: "$_id" }
}
}
] ).toArray();
This answer might also help you: https://stackoverflow.com/a/32134655/1742298

Related

MongoDB collection find method doesn't work not in order

I am trying to get some db collection depends on users ID.
const chat = await Chat.findOne({ users });
now this will work : "users": ["630200a45d22133dbe5bec44", "630200975d22133dbe5bec41"]
but this will not work: "users": [630200975d22133dbe5bec41", "630200a45d22133dbe5bec44"]
Same id's, just not in the right order.
You are looking for an exact match, so order matters. It seems what you want to be doing is to use $all, this checks all that the elements present in the input array exists in the db.
Additional you'll want to add a size check if you want to limit it so an exact match, otherwise documents like {"users": ["630200a45d22133dbe5bec44", "630200975d22133dbe5bec41", "otherid"] } will be matched.
Overall like so:
const chat = await Chat.findOne({
users: {
$all: [
"630200975d22133dbe5bec41",
"630200a45d22133dbe5bec44"
]
},
"users.2": {
$exists: false
}
})
Mongo Playground
Or dynamically based on input size:
const input = [
"630200975d22133dbe5bec41",
"630200a45d22133dbe5bec44"
];
const sizeKey = `users.${input.length}`
const chat = await Chat.findOne({
users: {
$all: input
},
[sizeKey]: {
$exists: false
}
})

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

using if conditions to summon appropriate stages in aggreagations

This below is an imaginary syntax i wish it was availabe so i could fetch my sessions with .
i have a Course collection that every single course has a sessions array as sub-document
i want to fetch courses based on my users query params when they search, so that if somebody asked for sessions from a specific teacher i use that in my $match stage in aggregate if not just find all sessions from all teacher , the same applies for subject and status if they get defined use them if not ignore them and find all possible.
there is another procedure if there was a keyword in mongo or aggregate that i could use and by that it knew that it find all something like * or regex syntax
i also come across to a $cond keyword but did not match my expectations in here .
app.get('/sessions',(req, res)=>{
const teacher = req.query.teacherId
const subject = req.query.subjectId
const status = req.query.statusId
Course.aggregate([
if(teacher) {$match:{teacher:teacher}},
if(subject) {$match:{subject:subject}},
if(status) {$match:{status:status}}
]).then(sessions=>res.json(sessions))
.catch(err=>res.json(err))
})
not sure if this helps but this is my Course Schema
const CourseSchema = new mongoose.Schema({
name:{type:String,required:true},
status:{type:String,required:true},
subject:{
type:mongoose.Schema.Types.ObjectId,
ref :'subjects'
},
teacher:{
type:mongoose.Schema.Types.ObjectId,
ref :'users'
},
sessions:[
{
Date:{type:Date,required:true},
timeStart:{type:String,required:true},
timeEnd :{type:String,required:true},
students :[{
type:mongoose.Schema.Types.ObjectId,
ref :'users'
}]
}
]
})
Thank You in advance .
I believe you are trying to achieve something like this:
app.get('/sessions', (req, res) => {
const teacher = req.query.teacherId
const subject = req.query.subjectId
const status = req.query.statusId
const query = [];
if (teacher) query.push({ $match: { teacher: teacher } });
if (subject) query.push({ $match: { subject: subject } });
if (status) query.push({ $match: { status: status } });
Course.aggregate(query).then(sessions => res.json(sessions))
.catch(err => res.json(err));
})
REMEMBER, I did not check if the query is okay.

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"] } } )

Get 2 documents in 1 MongoDB call

I am using MongoDB and Mongoose to retrieve documents from the database.
I have two IDs and I want to get the corresponding documents. I use
Collection.findById(id1).then(doc1 => {
if (doc1) {
Collection.findById(id2).then(doc2 => {
if (doc2) {
Is it possible to do this in a single call?
I am wondering if it can be done with
{doc1, doc2} = Collection.find({ _id: $in: [id1, id2] });
and if this is better than my original approach.
You can use mongoDB $in operator to retrieve multiple documents, the syntax is
db.inventory.find( { id: { $in: [ 5, 15 ] } } )

Resources