aggregate $push + $lookup - node.js

I need to populate inside array...
messageModel.aggregate([
{"$match": {$and: [
{$or: [{"to": system.mongoose.Types.ObjectId(userId)}, {"from": system.mongoose.Types.ObjectId(userId)}]}
]
}
},
{
"$group": {
"_id": "$conversationId",
"conversation": {"$push": {'from': "$from"}}
}
},
{"$lookup": {
"from": "user",
"localField": "conversation.from",
"foreignField": "_id",
"as": "to"
}},
{"$unwind": {"path": "$conversation.from"}},
{"$project": {
"conversation.from.firstName": "$conversation.from.firstName"
}
}
]
This return empty array what is wrong? it works when I don't use array, if just take $first element... Any solution?

Related

how to join two documents using $lookup mongodb

I have been trying to join two collection in MongoDb using the aggregate function but it seems it's not working for me, When I run api using lookup it show the me empty collection [],
I have tried with the following.
db.student.aggregate([
{
"$match": {
_id: "63c4c245188267e988d690e2"
},
},
{
"$lookup": {
"from": "wall",
"localField": "_user",
"foreignField": "_id",
"as": "wallpost"
}
}
])
Result:
Here is the result i m getting after lookup :(
[
{
"_id": "63c4c245188267e988d690e2",
"hereFor": [
{
"mainTag": "study",
"subtag": [
"studybuddy",
"findtutor"
]
}
],
"lastName": "Kumar",
"name": "Kamal",
"profilePicture": [
"https://airustudentimages.s3.ca-central-1.amazonaws.com/1673588594404-ba7777ef676f439f86aa612e8be67fd9"
],
"wallpost": []
}
]
Collections
Collection i m using in the query.
Student
student: [
{
"_id": "63c4c245188267e988d690e2",
"name": "Kamal",
"lastName": "Kumar",
"profilePicture": [
"https://airustudentimages.s3.ca-central-1.amazonaws.com/1673588594404-ba7777ef676f439f86aa612e8be67fd9"
],
"hereFor": [
{
"mainTag": "study",
"subtag": [
"studybuddy",
"findtutor"
]
}
],
},
{
"_id": "63c3965c201a1d738ab6867e",
"name": "Suraksha",
"lastName": "Singh",
"profilePicture": [
"https://airustudentimages.s3.ca-central-1.amazonaws.com/1673762449670-a8bdf9b9b0faf3ad84e0a5bc76e32fb8"
],
"hereFor": [
{
"mainTag": "study",
"subtag": [
"studybuddy",
"findtutor"
]
}
],
}
],
Wall
"wall": [
{
"_id": "63c4c92a188267e988d690e3",
"_user": "63c3965c201a1d738ab6867e",
"isSponsered": false,
"description": "Hello test case ",
"tag": {
"mainTag": "hostels"
},
"createdAt": "1673766717308",
"updatedAt": "1673766717308",
},
{
"_id": "63c4cc2b188267e988d690e5",
"_user": "63c3965c201a1d738ab6867e",
"isSponsered": false,
"description": "Hello test case 22 ",
"tag": {
"mainTag": "hostels"
},
"createdAt": "1673766717308",
"updatedAt": "1673766717308",
},
],
Have a look at https://mongoplayground.net/p/2moDXi3lygL
Your query is on Student collection. So the localField should be _id and and the foreignField should be _user (from wall collection).
Then it works fine.
db.student.aggregate([
{
"$match": {
_id: "63c3965c201a1d738ab6867e"
},
},
{
"$lookup": {
"from": "wall",
"localField": "_id",
"foreignField": "_user",
"as": "wallpost"
}
}
])
https://mongoplayground.net/p/r1JeQIlM7AA
You mix up the localField and foreignField.
From Equality Match with a Single Join Condition:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
It should be:
{
"$lookup": {
"from": "wall",
"localField": "_id",
"foreignField": "_user",
"as": "wallpost"
}
}
Demo # Mongo Playgound

How to get two arrays from mongo aggregate with $project and $map insdite ti

I have a nodejs app with Repository architecture. I am trying to get the data returned from an aggregation I made:
function foo(id) {
return await this.collection.aggregate([
{
"$match": {
_id: "ObjectId('"+ id +"')"
}
},
{
"$addFields": {
"self": "$$ROOT"
}
},
{
"$graphLookup": {
"from": "categories",
"startWith": "$_id",
"connectFromField": "_id",
"connectToField": "categoryId",
"as": "categoryLookup"
}
},
{
"$addFields": {
"categoryLookup": {
"$concatArrays": [
"$categoryLookup",
[
"$self"
]
]
}
}
},
{
"$lookup": {
"from": "locos",
"localField": "categoryLookup._id",
"foreignField": "categoryId",
"as": "locosLookup"
}
},
{
"$project": {
categories: {
"$map": {
"input": "$categoryLookup",
"as": "c",
"in": "$$c._id"
}
},
locos: {
"$map": {
"input": "$locosLookup",
"as": "l",
"in": "$$l._id"
}
}
}
}
]);
}
I want to get the data from the returned cursor which can not be transformed into an array. The problem is that this code works fine on the playground but I think also that $filed won't get the field since we need to use $getField { "fieldName": "field"}. I am really stuck here and the answers given to me previously weren't helping ..
the next step please

Aggregate query working on robo3T but not working in my code

I am trying to execute the aggregate query mentioned in the below, i am getting empty array. if i run the same query in the robo3T, I am getting the values. please Help me to find what am I missing.
Query:
var monthData=new Date();
console.log(new Date(monthData.getFullYear(), monthData.getMonth(), 2).toISOString());
monthData=await new Date(monthData.getFullYear(), monthData.getMonth(), 2).toISOString();
[err, data] = await to(LeadsLog.aggregate(
[
{ "$match": { "updatedAt":{$gte:monthData} }},
{ "$lookup": {
"from": "results",
"localField": "result",
"foreignField": "_id",
"as": "result"
}},
{ "$match": { "result.company": new mongoose.Types.ObjectId(companyId)}},
{ "$group": {
"_id": "$result.name",
"count": { "$sum": 1 }
}}
]))
Robo3T Query:
db.getCollection('leadsLog').aggregate(
[
{ "$match": { "updatedAt":{$gte:ISODate("2021-10-01T04:36:14.224Z")} }},
{ "$lookup": {
"from": "results",
"localField": "result",
"foreignField": "_id",
"as": "result"
}},
{ "$match": { "result.company":ObjectId("6114dc9193a52d3278aa486f")}},
{ "$group": {
"_id": "$result.name",
"count": { "$sum": 1 }
}}
])
Please Help me, Thank you.

convert array to string in $project (aggregate)

i use $project operation to specify the inclusion of fields i have this code:
[{
'$lookup': {
'from': 'users',
'localField': 'owner',
'foreignField': 'id'
'as': 'user'
}
}, {
'$project': {
'userName': '$user.username',
'userId': '$user.id'
}
}]
i have the result below:
[
{
"userName": [
"jscode"
],
"userId": [
"5d1888d60c627764aabd8b1e"
]
}
]
i need to convert userId and userName results from array to string like this:
[
{
"userName": "jscode" ,
"userId": "5d1888d60c627764aabd8b1e"
}
]
thanks :)
You can use below $project stage
{
"$project": {
"userName": { "$arrayElemAt": ["$user.username", 0] },
"userId": { "$arrayElemAt": ["$user.id", 0] }
}
}
Or Using $unwind
[
{ "$lookup": {
"from": "users",
"localField": "owner",
"foreignField": "id",
"as": "user"
}},
{ "$unwind": "$user" },
{ "$project": {
"userName": "$user.username",
"userId": "$user.id"
}}
]
Actually $lookup always returns the new field in form of array. So to pick the field from that array you either need to use $unwind or can $arrayElemAt to pick the 0th element.

How to perform multiple $lookup for array mongodb aggregate

How can i perform $lookup in aggregate (mongodb) for an array
{
messages: [{
"_id" : ObjectId("5bfc43f2bbc4176ecc1c5f83"),
"text" : "text1",
"sender" : {
"id" : "36046fc2e70dd508a0bf1f36fd2daa20"
}
}, {
"_id" : ObjectId("5bfc43f2bbc4176ecc1c5f83"),
"text" : "text2",
"sender" : {
"id" : "36046fc2e70dd508a0bf1f36fd2daa22"
}
}],
"filed1": { ... },
"filed2": { ... }
}
how can i do a $lookup for sender id from accounts collection?
tried:
...
{
$lookup: {
from: "accounts",
localField: "messages.sender.id",
foreignField: "id",
as: "messages.sender.user"
}
}
...
You can use below aggregation
db.collection.aggregate([
{ "$unwind": "$messages" },
{ "$lookup": {
"from": "accounts",
"localField": "messages.sender.id",
"foreignField": "id",
"as": "messages.sender.user"
}},
{ "$unwind": "$messages.sender.user" }
{ "$group": {
"_id": "$_id",
"messages": { "$push": "$messages" },
"filed1": { "$first": "$filed1" },
"filed2": { "$first": "$filed2" }
}}
])

Resources