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