Hello guys I have been working on a project where I am building a chat app
so I have a model for chatting like this
const chatSchema = new mongoose.Schema(
{
participants: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
messages: [
{
from: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
message: String,
date: {
type: Date,
default: Date.now,
},
delivered: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
seen: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
},
],
isGroup: {
type: Boolean,
default: false,
},
groupName: {
type: String,
},
admins: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
],
},
{ timestamps: true },
);
Now to get messages from this schema I am writing the following MongoDB aggregation query
const aggregateQuery: PipelineStage[] = [
{
$match: findQuery,
},
{
$unwind: '$messages',
},
{
$lookup: {
from: 'users',
localField: 'messages.from',
foreignField: '_id',
as: 'messages.from',
pipeline: [
{
$project: {
username: 1,
name: 1,
email: 1,
},
},
],
},
},
{
$unwind: '$messages.from',
},
{
$sort: {
'messages.date': -1,
},
},
{
$group: {
_id: '$_id',
'sortedMessages': { $push: '$messages' },
participants: { $first: '$participants' },
isGroup: { $first: '$isGroup' },
groupName: { $first: '$groupName' },
admins: { $first: '$admins' },
},
},
{
$project: {
messages: {
$reverseArray: {
$slice: ['$sortedMessages', skip, limit],
},
},
groupName: 1,
participants: 1,
isGroup: 1,
admins: 1,
count: {
$size: '$sortedMessages',
},
},
},
{
$lookup: {
from: 'users',
localField: 'participants',
foreignField: '_id',
as: 'sender',
pipeline: [
{
$match: {
_id: {
$ne: new mongoose.Types.ObjectId(userId),
},
},
},
{
$limit: 1,
},
{
$project: {
username: 1,
name: 1,
email: 1,
},
},
],
},
},
{
$unwind: '$sender',
},
];
Now the problem is when an array of messages has some values because whenever I create a chat document I assign an empty array inside it like this []
so when hitting this query and
If the array is empty then even though the match query finds the result comes as an empty array without any data
but if the message array has something in it then data comes as expected.
I can not figure out what I am doing wrong here.
the find query goes like this
const findQuery = {
participants: {
$in: [new mongoose.Types.ObjectId(req.user?._id)]
}
NOTE: I checked server times userId is there. 🙂
Here is a document without messages and with messages
with messages ⬇️
{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859f0"
},
"participants": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
},
{
"$oid": "62c9a0f5dfb6cf9c7fe859cf"
}
],
"messages": [
{
"from": {
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
},
"message": "Hi this is first message.",
"delivered": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
}
],
"seen": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
}
],
"_id": {
"$oid": "62c9a3464fe8c3886b2aed37"
},
"date": {
"$date": {
"$numberLong": "1657381702152"
}
}
},
{
"from": {
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
},
"message": "Hi this is first message.",
"delivered": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
}
],
"seen": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
}
],
"_id": {
"$oid": "62c9a75495dedf71b6028b55"
},
"date": {
"$date": {
"$numberLong": "1657382740772"
}
}
}
],
"isGroup": false,
"admins": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
},
{
"$oid": "62c9a0f5dfb6cf9c7fe859cf"
}
],
"createdAt": {
"$date": {
"$numberLong": "1657381109954"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657382740775"
}
},
"__v": 2
}
And here is a document with an empty array ⬇️
{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859f2"
},
"participants": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e5"
},
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
}
],
"messages": [],
"isGroup": false,
"admins": [
{
"$oid": "62c9a0f5dfb6cf9c7fe859e5"
},
{
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
}
],
"createdAt": {
"$date": {
"$numberLong": "1657381109958"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109958"
}
},
"__v": 0
}
In this scenario when I run the query document with data is coming but second document which has empty array is not getting returned.
This is my user's collection
[{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859c5"
},
"name": "Norberto Becker",
"email": "corine5@gmail.com",
"username": "juwan.king26",
"password": "$2b$08$w5KowVsCZMt3rD9CrfJ3y.CXQf0EJ8x/akvaVw4qWN4O1LKtHr2ii",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109567"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109567"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859c9"
},
"name": "Austen Anderson",
"email": "yesenia65@hotmail.com",
"username": "ricky.gleichner1",
"password": "$2b$08$0U6awlfx0lfm2.wW9xhI0.rmIVwSvbvta5RWBp2bkrOQbuhL45aO2",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109590"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109590"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859cb"
},
"name": "Karlie McLaughlin",
"email": "estefania.nienow11@gmail.com",
"username": "samantha96",
"password": "$2b$08$HcaYbfcvKVkc2DRD4Ek2.OU2kSX.HxqjwUw44R2xkfAlAkxXwFinG",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109608"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109608"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859cd"
},
"name": "Joey McLaughlin",
"email": "lucas26@hotmail.com",
"username": "schuyler73",
"password": "$2b$08$hJrocpP.ablQgF/LzklO7O4ofvgLd3k/xsqfhfwLgrNxqRG2CwtYm",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109626"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109626"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859cf"
},
"name": "Omer Mann",
"email": "taylor44@hotmail.com",
"username": "travis93",
"password": "$2b$08$tXT4CetLDAql46VmC0wDKuXUt5TCkvYINf79MMuvBnh/TdTEtkDIS",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109646"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109646"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859d1"
},
"name": "Solon Jacobi",
"email": "jammie1@yahoo.com",
"username": "erna_quitzon",
"password": "$2b$08$4DODzEWneeIOlT/8o4C5huOg/bD8cJft2F5JJnnCuqdw95yYMl9DC",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109665"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109665"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859d3"
},
"name": "Theresia Gutkowski",
"email": "maudie9@yahoo.com",
"username": "baby36",
"password": "$2b$08$65YHzbE57lG7dBF1d/aErOiYbQq/YIPiL4clxJwkP7xViumQk8u0K",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109683"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109683"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859d5"
},
"name": "Neil Kshlerin",
"email": "ayana53@yahoo.com",
"username": "alek_braun",
"password": "$2b$08$lUwqxHK27fe/Aq.LQWtjHOzDp86di3Zd7vj.0tqVkjGqJtzuf5/0.",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109703"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109703"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859d7"
},
"name": "Jackeline Gibson",
"email": "calista4@yahoo.com",
"username": "albertha.miller9",
"password": "$2b$08$69Y6sJbGwIqCn5FkI5wzjuYpdWD.bN0kMWJIANI89NYhIbJhV5FBa",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109721"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109721"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859d9"
},
"name": "Luisa Koelpin",
"email": "alexandra15@gmail.com",
"username": "jimmie11",
"password": "$2b$08$k7K0CmZAU3PAmcamQtdTZOAaFU.4cXW5IGCMKG2RIml2sSA1Enice",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109739"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109739"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859db"
},
"name": "Joel Cruickshank",
"email": "rodrigo19@hotmail.com",
"username": "eldridge.will20",
"password": "$2b$08$30NCVEgtg0ydsD3.Azc9BOaetu5mxwybih9Y5Btu.IjMVjpbIPxiG",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109758"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109758"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859dd"
},
"name": "Nigel Walsh",
"email": "emile_little@hotmail.com",
"username": "emmie_hilpert",
"password": "$2b$08$HsS37V8dy8T.uiZPkKqYnuL87QvXYPnms9ImV5DaYkxiNQ1ErRili",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109775"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109775"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859df"
},
"name": "Freddie Stehr",
"email": "tony85@yahoo.com",
"username": "flossie4",
"password": "$2b$08$ypyqxVunL4cbaa8GlW0xiODupiK3tW9lvY1XDLWKqsU62ehJ7ma1S",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109799"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109799"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859e1"
},
"name": "Helene Treutel",
"email": "eula.mclaughlin17@yahoo.com",
"username": "alice32",
"password": "$2b$08$TFwuY7YUN/ilF.xfwmtY8.5RZl1mT4scSAkw83SzRgE2jGA3ILiXq",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109821"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109821"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859e3"
},
"name": "Edythe Grimes",
"email": "roma_mckenzie17@yahoo.com",
"username": "malcolm.batz",
"password": "$2b$08$KM6fCyJataf4UN7XrkYxY.HPatrfskqHJaFeGEyn4HU19/NkSzoiS",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109841"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109841"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859e5"
},
"name": "Deondre Ernser",
"email": "verner_hudson@hotmail.com",
"username": "suzanne14",
"password": "$2b$08$dkhdUJp4RHraX/4cTq7XZOclpohxKgC5vaUPnXb0YmQzfkbx9lC0a",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109860"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109860"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859e7"
},
"name": "Roger Weber",
"email": "mercedes.bayer@gmail.com",
"username": "carrie_feil41",
"password": "$2b$08$nReH9kaoLKmMX9Um9Ap/IeBhRRQZv5wSVjQaQvOnYlhEl9PSqreXq",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109877"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109877"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859e9"
},
"name": "Thelma Reinger",
"email": "julie9@gmail.com",
"username": "isaac19",
"password": "$2b$08$Abbk7fC1BU1mtzQfwJA8ReYOkjCbBAadEd92rCUMLnw59hSOow3Ou",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109897"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109897"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859eb"
},
"name": "Hillard Beer",
"email": "durward55@hotmail.com",
"username": "blaze_weissnat",
"password": "$2b$08$2MpQwgsvWLu52QZQNt1YT.Ih295gSG3WlWnWiamKVg67W3IylGENu",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109915"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109915"
}
},
"__v": 0
},{
"_id": {
"$oid": "62c9a0f5dfb6cf9c7fe859ed"
},
"name": "Santino Klocko",
"email": "jamil19@hotmail.com",
"username": "bertrand_schinner73",
"password": "$2b$08$KOKO2GU/QPIyWYLXqbVyE.FhizfrsLUZ/EOY.Zjd0mIoBX8Zdn36a",
"isVerified": true,
"friendRequests": [],
"friends": [],
"createdAt": {
"$date": {
"$numberLong": "1657381109931"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1657381109931"
}
},
"__v": 0
}]
I'm not sure what is your expected results, but I think it is something close to the results if this simple query:
db.orders.aggregate([
{$lookup: {
from: "users",
localField: "participants",
foreignField: "_id",
as: "participants",
pipeline: [{$project: {username: 1, name: 1, email: 1}}]
}
},
{$set: {
messages: {
$map: {input: "$messages",
in: {$mergeObjects: [
"$$this",
{from: {
$arrayElemAt: [
"$participants",
{$indexOfArray: ["$participants._id", "$$this.from"]}
]
}
}
]
}
}
}
}
}
])
See how it works on the playground example