$lookup or joins is not working in mongodb - mongodb

I want to get another datatable field along with response data, as like join ($lookup) in mongodb, but its giving empty output of join table. Here is my code..
Releases.aggregate([
{ "$sort": { "release_date": -1 } },
{ "$limit": 10 },
{ "$lookup": {
"from": "companies", // actual schema name Company
"localField": "company_id",
"foreignField": "_id",
"as": "companyinfo"
} },
])
its giving the empty array companyinfo, and in the schema I create " Company " but in database, its automatic change it with " companies "
here is sample document
{
"_id": {
"$oid": "xxxxxxxxxxxx"
},
"company_id": "xxxxxxxxxxxxxxxxx",
"heading": "testing",
"description": "testing",
"key_point": "filename",
"release_date": "2018-12-01T00:00:00.000Z",
"datetime": {
"$date": "2018-12-03T14:53:57.031Z"
},
"__v": 0,
}
and I want output fields {heading, description, key_point, release_date, companyinfo.company_email} only, any idea ? Thanks in advance

Related

Mongodb , "JOIN" a nested object

I need to join the faults array
{
"_id": "99812930-37CE-456F-A9D9-837E9E3F712A",
"faultsChanged": [
{
"_id": "7C628A46-7E80-4615-8B08-10C5E9A6B1D7",
"faults": [
"BF221A71-0217-42E7-B853-53112EDA9694",
"E4A54172-7E93-49C4-840B-8E6116116979"
],
"isDeleted": false,
"partition": "indego",
"sessionUuid": "A83CE9A1-7539-493F-8BA4-6FBE25B18B57",
"source": "1",
"timestamp": {
"$date": {
"$numberLong": "1630603342700"
}
},
"unmigratedNote": null,
"uuid": "7C628A46-7E80-4615-8B08-10C5E9A6B1D7"
}
]
}
So that it gets replaced by a document from another collection OOFaultEntry.
New to the aggregation pipeline, I have tried
{$lookup:{
from: "OOFaultEntry",
localField: 'faultsChanged.faults',
foreignField: "_id",
let:{faults:"$faultsChanged.faults"},
pipeline:[],
as:"faults"
}}
but this just created a key on the result and was not embedded inside of each respective faultChanged object
expected result
OOFaultEntry would be JOINED on _id . So ,it should look something like
{
"_id": "99812930-37CE-456F-A9D9-837E9E3F712A",
"faultsChanged": [
{
"_id": "7C628A46-7E80-4615-8B08-10C5E9A6B1D7",
"faults": [
{
"_id": "BF221A71-0217-42E7-B853-53112EDA9694",
"some_key": "value"
},
{
"_id": "E4A54172-7E93-49C4-840B-8E6116116979",
"some_key": "value"
}
],
"isDeleted": false,
"partition": "indego",
"sessionUuid": "A83CE9A1-7539-493F-8BA4-6FBE25B18B57",
"source": "1",
"timestamp": {
"$date": {
"$numberLong": "1630603342700"
}
},
"unmigratedNote": null,
"uuid": "7C628A46-7E80-4615-8B08-10C5E9A6B1D7"
}
]
}
One way would be $unwind the faultsChanged array first. Perform the $lookup and regroup the results.
db.Faults.aggregate([
{
"$unwind": "$faultsChanged"
},
{
"$lookup": {
"from": "00FaultEntry",
"localField": "faultsChanged.faults",
"foreignField": "_id",
"as": "faultsChanged.faults"
}
},
{
"$group": {
"_id": "$_id",
"faultsChanged": {
$push: "$faultsChanged"
}
}
}
])
Mongo Playground

How to properly lookup for several fields in mongodb?

Let's say i have 2 collections
// Post collection:
{
"_id": "61f7a933b209737de4cc2657",
"author": "61d30188cf93e83e08d14112",
"title": "Some title",
"createts": 1643620659355
}
// User collection:
{
"_id": "61d30188cf93e83e08d14112",
"nickname": "Bob",
"link": "bobspage"
}
And i need to get this result
{
"_id": "61f7a933b209737de4cc2657",
"author": {
"_id": "61d30188cf93e83e08d14112",
"nickname": "Bob",
"link": "bobspage"
},
"title": "Some title",
"createts": 1643620659355
}
How can i make a request with aggregation, which will display this output ?
Simply use $lookup in an aggregation query:
First $lookup, which generate a field called author which is an array with all values joined.
To get author as an object get the first result for the array using $arrayElemAt.
db.post.aggregate([
{
"$lookup": {
"from": "user",
"localField": "author",
"foreignField": "_id",
"as": "author"
}
},
{
"$addFields": {
"author": {
"$arrayElemAt": [
"$author",
0
]
}
}
}
])
Example here

Mongoose aggregate internal lookup grouping by field

I'm trying to group all distinct fields and then lookup into another table , the problem is that I'm adding too many results for the same user inside the lookup, so I wonder how can I group those results internally and then in the next stage add another lookup to a different table.
Currently I have the following code:
Post.aggregate([
{ "$group" : {"_id" : { "id_fanpage": "$id_fanpage" },"total": { $sum: 1 } } },
{
"$lookup": {
"from": "v3_post_reaccion_angry",
"localField": "_id.id_fanpage",
"foreignField": "id_fanpage",
"as": "resultingAngries"
}
},
{
"$lookup": {
"from": "v3_post_reaccion_compartir",
"localField": "_id.id_fanpage",
"foreignField": "id_fanpage",
"as": "resultingCompartir"
}
}
]).exec(function(err, results){
console.log(results);
return results
}).then(success(res))
What I'm trying to do is distinct Post rows by "id_fanpage", then join another table by that returned id_fanpage, which is basically working as expected, the results are this:
{
"_id": {
"id_fanpage": "5a63a96d1aa940ca0ada1c82"
},
"total": 831,
"resultingAngries": [
{
"_id": "5a71ccda1aa940dd154caf83",
"id_post": "5a71ccda1aa940dd154caf82",
"id_fanpage": "5a63a96d1aa940ca0ada1c82",
"facebook_usuario_id": 345346565665,
"facebook_usuario_nombre": "AAAAAAAAAAAAAAAAA"
},
{
"_id": "5a71cd6b1aa940dd154ddb43",
"id_post": "5a71cd6b1aa940dd154ddb40",
"id_fanpage": "5a63a96d1aa940ca0ada1c82",
"facebook_usuario_id": "44444444444444444",
"facebook_usuario_nombre": "XXXXXXXXXXXXXXXX"
},
{
"_id": "5a71d7f61aa940dd156b60f4",
"id_post": "5a71d7f61aa940dd156b60e9",
"id_fanpage": "5a63a96d1aa940ca0ada1c82",
"facebook_usuario_id": "asdf12345232421",
"facebook_usuario_nombre": "YYYYYYYYYYYYYY"
},
{
"_id": "5a71cde11aa940dd154ec514",
"id_post": "5a71cde11aa940dd154ec513",
"id_fanpage": "5a63a96d1aa940ca0ada1c82",
"facebook_usuario_id": "asdf2345234555",
"facebook_usuario_nombre": "ZZZZZZZZZZZZZZ"
},
{
"_id": "5a71cdcb1aa940dd154e917a",
"id_post": "5a71cdcb1aa940dd154e9178",
"id_fanpage": "5a63a96d1aa940ca0ada1c82",
"facebook_usuario_id": "44444444444444444",
"facebook_usuario_nombre": "XXXXXXXXXXXXXXX"
}
]
}
Now the problem is, I want to group all results inside resultingAngries by facebook_usuario_id and also be able to add the the same to the next lookup, but as far as I know I cannot use a group after the first lookup without affecting the next lookup.
So the result should be:
{
"_id": {
"id_fanpage": "5a63a96d1aa940ca0ada1c82"
},
"total": 831,
"resultingAngries": [
{
"_id": "this is my user id 1111111111",
"count": N,
},
{
"_id": "this is my user id 2222222222",
"count": Y,
}
],
"resultingLikes": [
{
"_id": "this is my user id 1111111111",
"count": N,
},
{
"_id": "this is my user id 2222222222",
"count": Y,
}
],
},
{
"_id": {
"id_fanpage": "5a63a96d1aa942345wedf23455s"
},
"total": 20,
"resultingLikes": [
{
"_id": "this is my user id 1111111111",
"count": N,
},
{
"_id": "this is my user id 2222222222",
"count": Y,
}
],
},
"resultingAngries": [
{
"_id": "this is my user id 1111111111",
"count": N,
},
{
"_id": "this is my user id 2222222222",
"count": Y,
}
],
And so on.
I already have seen aggregate, and lookups and not sure if $addToSet can make it, because I cannot group internally so far so applying addToSet is giving me hard times. Help would be appreciate.
Insert below three stages between your $lookup's.
The below steps $unwind resultingAngries array followed by first $group to count the distinct combination of facebook_usuario_id & id_fanpage and second $group to $push the count and facebook_usuario_id back into resultingAngries array.
{"$unwind":"$resultingAngries"},
{"$group":{
"_id":{
"id_fanpage":"$_id.id_fanpage",
"facebook_usuario_id":"$resultingAngries.facebook_usuario_id"
},
"total":{"$first":"$total"},
"count":{"$sum":1}
}},
{"$group":{
"_id":{"id_fanpage":"$_id.id_fanpage"},
"total":{"$first":"$total"},
"resultingAngries":{
"$push":{
"_id":"$_id.facebook_usuario_id",
"count":"$count"
}
}
}}

How to combine multiple collections and merge the joined documents into a single document

Here is the problem, I am unable to get the following result. Please look into the piece of json and help me out.
This is my data:
[
{
"user_id": "65asdfksadjfk3u4",
"lat": 23.4343,
"long": 15.2382
}
]
Currently my result is:
[
{
"_id": "65asdfksadjfk3u4",
"name": "Srini",
"age": 26,
"some other key": "some other values"
}
]
I need to get the collection from the user_id and add it to the same array object. As you can notice both lat and long are being removed in my current result.
[
{
"_id": "65asdfksadjfk3u4",
"name": "Srini",
"age": 26,
"some other keys": "some other values",
"lat": 23.4343,
"long": 15.2382
}
]
You can append the $lookup stage to join the current pipeline results with the users collections by the user_id fields and then use $mergeObjects in the $replaceRoot to merge the joined documents from users and the current results:
db.collection.aggregate([
/* current pipeline here */
{ "$lookup": {
"from": "users",
"localField": "_id",
"foreignField": "user_id",
"as": "user"
} },
{ "$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{ "$arrayElemAt": [ "$user", 0 ] },
"$$ROOT"
]
}
} },
{ "$project": { "user": 0, "user_id": 0 } }
]);

How to use MongoDBs aggregate `$lookup` as `findOne()`

So as you all know, find() returns an array of results, with findOne() returning just a simply object.
With Angular, this makes a huge difference. Instead of going {{myresult[0].name}}, I can simply just write {{myresult.name}}.
I have found that the $lookup method in the aggregate pipeline returns an array of results instead of just a single object.
For example, I have two colletions:
users collection:
[{
"firstName": "John",
"lastName": "Smith",
"country": 123
}, {
"firstName": "Luke",
"lastName": "Jones",
"country": 321
}]
countries collection:
[{
"name": "Australia",
"code": "AU",
"_id": 123
}, {
"name": "New Zealand",
"code": "NZ",
"_id": 321
}]
My aggregate $lookup:
db.users.aggregate([{
$project: {
"fullName": {
$concat: ["$firstName", " ", "$lastName"]
},
"country": "$country"
}
}, {
$lookup: {
from: "countries",
localField: "country",
foreignField: "_id",
as: "country"
}
}])
The results from the query:
[{
"fullName": "John Smith",
"country": [{
"name": "Australia",
"code": "AU",
"_id": 123
}]
}, {
"fullName": "Luke Jones",
"country": [{
"name": "New Zealand",
"code": "NZ",
"_id": 321
}]
}]
As you can see by the above results, each country is an array instead of a single object like "country": {....}.
How can I have my $lookup return a single object instead of an array since it will only ever match a single document?
You're almost there, you need to add another $project stage to your pipeline and use the $arrayElemAt to return the single element in the array.
db.users.aggregate(
[
{ "$project": {
"fullName": {
"$concat": [ "$firstName", " ", "$lastName"]
},
"country": "$country"
}},
{ "$lookup": {
"from": "countries",
"localField": "country",
"foreignField": "_id",
"as": "countryInfo"
}},
{ "$project": {
"fullName": 1,
"country": 1,
"countryInfo": { "$arrayElemAt": [ "$countryInfo", 0 ] }
}}
]
)
You can also use "preserveNullAndEmptyArrays"
Like so:
db.users.aggregate(
[
{ "$project": {
"fullName": {
"$concat": [ "$firstName", " ", "$lastName"]
},
"country": "$country"
}},
{ "$lookup": {
"from": "countries",
"localField": "country",
"foreignField": "_id",
"as": "countryInfo"
}},
{"$unwind": {
"path": "$countryInfo",
"preserveNullAndEmptyArrays": true
}
},
]
)
db.users.aggregate([
{
$lookup: {
from: 'countries',
localField: 'country',
foreignField: '_id',
as: 'country'
}
},
{
$unwind: '$country'
}
]).pretty()
You can use this mongo query for getting the country object
When you don't want to repeat all fields in project, just overwrite the field in question with $addFields:
db.users.aggregate([
{ "$project": {
"fullName": {
"$concat": [ "$firstName", " ", "$lastName"]
},
"country": "$country"
}},
{ "$lookup": {
"from": "countries",
"localField": "country",
"foreignField": "_id",
"as": "countryInfo"
}},
{ "$addFields": {
"countryInfo": {
"$arrayElemAt": [ "$countryInfo", 0 ]
}
}}
])
I think the cleanest approach would be to add another step to the pipeline:
...,
{
$addFields : {
$country: { $first: '$country' }
}
}