Aggregation when one document contains the values of multiple Documents - mongodb

am trying to aggregate values of multiple documents in one, but unable to do it,
db.doc1.find().pretty();
{
"addressId" : ObjectId("5901a5f83541b7d5d3293768"),
"socialId" : ObjectId("5901b0f6d318b072ceea44fb")
}
db.doc2.find().pretty();
{
"_id" : ObjectId("5901a5f83541b7d5d3293768"),
"address" : "Gurgaon",
"mob" : "9876543211"
}
db.doc3.find().pretty();
{
"_id" : ObjectId("5901b0f6d318b072ceea44fb"),
"fbURLs" : "http://www.facebook.com",
"twitterURLs" : "http://www.twitter.com"
}
My Query
db.doc2.aggregate([
{ $match: { "_id" : ObjectId("5901a5f83541b7d5d3293768") } },
{
$lookup:
{
from: "doc1",
localField: "_id",
foreignField: "addressId",
as: "Doc2Details"
}
}
]).pretty();
db.doc3.aggregate([
{ $match: { "_id" : ObjectId("5901b0f6d318b072ceea44fb") } },
{
$lookup:
{
from: "doc1",
localField: "_id",
foreignField: "socialId",
as: "tireConfig"
}
}
]).pretty();
I want match values from Doc1 and combine values of doc2 and doc3, can someone help me with this?

Related

Populate nested array objects using aggregate in mongodb

Im trying to populate the second nested array after using aggregate $lookup.
This is my original array.
{
"_id" : ObjectId("607da9c0c7cb26384c7810a6"),
"date" : ISODate("2021-04-20T00:00:00.000+0000"),
"clientID" : "601e6dc61766587af8ce76db",
"medications" : [
{
"_id" : ObjectId("6065de3aa95e721f587f7528")
},
]
}
{
from: "medications",
localField: "medications._id",
foreignField: "_id",
as: "medications",
}
after using aggregate $lookup I get this result, but I still have nested array "inventory" that I need to populate. I tried adding another $lookup pipeline, but I don't know how the right way to do that.
{
"_id" : ObjectId("607da9c0c7cb26384c7810a6"),
"date" : ISODate("2021-04-20T00:00:00.000+0000"),
"clientID" : "601e6dc61766587af8ce76db",
"medications" : {
"_id" : ObjectId("6065de3aa95e721f587f7528"),
"medication": "med 1"
"schedule": ["9am", "10pm"]
"inventory": "ObjectId("6076d55ab6aeb947dca85877")"
}
}
This is the inventory item
{
"_id" : ObjectId("6076d55ab6aeb947dca85877"),
"item": "Inventory item 1",
"Qty": "10"
}
Expected Output
{
"_id" : ObjectId("607da9c0c7cb26384c7810a6"),
"date" : ISODate("2021-04-20T00:00:00.000+0000"),
"clientID" : "601e6dc61766587af8ce76db",
"medications" : {
"_id" : ObjectId("6065de3aa95e721f587f7528"),
"medication": "med 1"
"schedule": ["9am", "10pm"]
"inventory": {
"_id" : ObjectId("6076d55ab6aeb947dca85877"),
"item": "Inventory item 1",
"Qty": "10"
}
}
}
You can try this one or alternatively use population.
{
from: "medications",
localField: "medications._id",
foreignField: "_id",
as: "medications",
}
, {
$unwind: {
path: "$medications",
preserveNullAndEmptyArrays: true
}
}, {
$lookup: {
from: "inventory",
localField: "inventory._id",
foreignField: "_id",
as: "medications.inventory",
}
}
You may check the $unwind in the official documentation. Just pay attention to the appropriate localField and foreignField.
use populate() to expand nested references.
schemaModel.populate(result, {path: 'result'});
See more at Mongoose docs

Aggregate Query returns null array

I have three collections in EmployeeDB.
Employee
{
"user_id" : "EMP001",
"FirstName" : "Manoj",
"LastName" : "sharma",
"Status" : "0/1",
"CreateDate" : "1988-10-11T18:30:00.000Z"
}
EmpContact
{
"user_id" : "EMP001",
"Phone" : "9999999999",
"Email" : "xyz#gmail.com"
}
EmpInfo
{
"user_id" : "EMP001",
"Gender" : "Male",
"Age" : NumberInt(20),
"Designation" : "manager",
"Salary" : "5000"
}
I need to group the three collections and display all fields.
I tried the below code,
db.Employee.aggregate([
{$lookup: {from: "EmpContact",localField: "user_id",foreignField: "user_id",as: "contact"}},
{$unwind:"$EmpContact"},
{$lookup: {from: "EmpInfo",localField: "user_id",foreignField: "user_id",as: "empinfo"}},
{$unwind:"$EmpInfo"},
{
$match:{user_id : "EMP001"}
}
]).toArray();
But I got an empty array, Please help me...
The problem comes from your $unwind.
Since you name your field as contact in the $lookup, the field EmpContact doesn't exist.
The same thing for the second unwind, EmpInfo doesn't exist but empinfo does
Here is the full query
db.Employee.aggregate([
{
$lookup: {
from: "EmpContact",
localField: "user_id",
foreignField: "user_id",
as: "contact"
}
},
{
$unwind: "$contact"
},
{
$lookup: {
from: "EmpContact",
localField: "user_id",
foreignField: "user_id",
as: "empinfo"
}
},
{
$unwind: "$empinfo"
},
{
$match: {
user_id: "EMP001"
}
}
])
Try it here

MongoDB Aggregate - how to have TWO '$lookup' operations work?

I have the following aggregate query:
db.getCollection('village').aggregate([
{
"$match": { _id: "111" }
},
{
"$lookup": {
from: "character",
localField: "chieftainId",
foreignField: "_id",
as: "chieftain"
},
"$lookup": {
from: "character",
localField: "villagerIds",
foreignField: "_id",
as: "villager"
}
},
{ "$project" : { "villagerIds" : 0}}
])
And this is its result:
{
"_id" : "111",
"name" : "MyVillage",
"chieftainId" : "222",
"reputation" : 0,
"villagers" : [
{
"_id" : "333",
"name" : "Bortan",
"age" : 21,
"bloodlineId" : "7f02191f-90af-406e-87ff-41d5b4387999",
"villageId" : "foovillage",
"professionId" : "02cbb10a-6c0f-4249-a932-3f40e12d32c5"
},
{
"_id" : "444",
"name" : "Blendi",
"age" : 21,
"bloodlineId" : "b3a8ffeb-27aa-4e2e-a8e6-b382554f326a",
"villageId" : "foovillage",
"professionId" : "45dc9350-c84a-491d-a49a-524834dd5773"
}
]
}
As you can see villagerIds has been resolved to villagers. However chieftainId has not been resolved to chieftain. When I omit the second $lookup (with villager) then chieftain is being resolved successfully. It seems that only one $lookup will be effective and not both. Any idea how I can make both work?
Use separate pipeline for both $lookup
db.getCollection('village').aggregate([
{
"$match": { _id: "111" }
},
{
"$lookup": {
from: "character",
localField: "chieftainId",
foreignField: "_id",
as: "chieftain"
}
},
{
"$lookup": {
from: "character",
localField: "villagerIds",
foreignField: "_id",
as: "villager"
}
},
{ "$project" : { "villagerIds" : 0}}
])

join two collections in mongoDB

I have below two collections
db.sample.find().pretty()
{
"_id" : ObjectId("5930093eb3aaa7c02d4cbcdc"),
"name" : "Ashish",
"posts" : [
{
"_id" : ObjectId("59301c39028afaf3450e2444"),
"post" : ObjectId("59301c39028afaf3450e2885")
},
{
"_id" : ObjectId("59301c39028afaf3450e2445"),
"post" : ObjectId("59301c39028afaf3450e2889")
}
]
}
and other one
db.posts.find().pretty()
{ "_id" : ObjectId("59301c39028afaf3450e2885"), "title" : "test1" }
{ "_id" : ObjectId("59301c50028afaf3450e2889"), "title" : "test2" }
I want to join these two based on matching posts._id & sample.post._id value.
& create structure showing "Title" value as below:
In short create structure which shows post liked by each user.
"name" : "Ashish",
"posts" : [
{
"post" : ObjectId("59301c39028afaf3450e2889"),
"title" :"test2"
},
{
"post" : ObjectId("59301c39028afaf3450e2885"),
"title" :"test1"
},
we can join two collection using $lookup some thing like this
db.sample.aggregate([
{
$lookup:
{
from: "posts",
localField: "posts.post",
foreignField: "_id",
as: "samplepost"
}
}
])
https://docs.mongodb.com/v3.2/reference/operator/aggregation/lookup/
You can test it
db.sample.aggregate([
{$unwind: "$posts"},
{
$lookup: {
from: "posts",
localField: "posts.post",
foreignField: "_id",
as: "post"
}
},
{
$group: {
_id: "$_id",
name: {$first: "$name"},
posts: {
$push: {
post: {$arrayElemAt: ["$post._id", 0]},
title: {$arrayElemAt: ["$post.title", 0]}
}
}
}
}
])

How can I do a lookup in mongoDB with two foreign keys?

Three collections Product, ProductDescription, Language like this:
> db.Language.find();
{
"_id" : ObjectId("1234..."),
"isoCc" : "EN"
}
{
"_id" : ObjectId("5678..."),
"isoCc" : "DE"
}
> db.Product.find();
{
"_id" : ObjectId("3eff..."),
"sku" : "123456",
"title" : "Some Product Title"
}
> db.ProductDescription.find();
{
"_id" : ObjectId("44ad..."),
"ofProduct" : ObjectId("3eff..."),
"ofLanguage" : ObjectId("1234..."),
"shortDescription" : "English description"
}
{
"_id" : ObjectId("f5aa..."),
"ofProduct" : ObjectId("3eff..."),
"ofLanguage" : ObjectId("5678..."),
"shortDescription" : "German description"
}
If I do a lookup on the ProductDescription like this
db.Product.aggregate([
{
$lookup:
{
from: "ProductDescription",
localField: "_id",
foreignField: "ofProduct",
as: "description"
}
}
])
I get both entrys of ProductDescription.
So how can I also filter what language the description should be?
If you want to lookup description language also then you need to use another lookup for description.ofLanguage
db.Product.aggregate([
{
$lookup:
{
from: "ProductDescription",
localField: "_id",
foreignField: "ofProduct",
as: "description"
}
},
{
$lookup:
{
from: "Language",
localField: "description.ofLanguage",
foreignField: "_id",
as: "language"
}
}
])