Not able to access object value by dynamic key in mongoDB - mongodb

I have two collections i.e parent and chilednodes.
parent collection :
{
"_id" : "5e6c70e8996ddf1c28e14504",
"startDate" : "2020-02-25T14:01:58.697Z",
"active_id" : "child_vesrion_1",
"child_id" : "5e5e2cd4e972a95b6c32b5bf30"
}
chilednodes:
{
"_id" : "5e5e2cd4e972a95b6c32b5bf30",
"startDate" : "2020-02-25T14:01:58.697Z",
"endDate" : null,
"child_vesrion_1" : {
"childName" : "xyz",
"createdDate" : "2020-02-25T14:01:58.697Z",
"text" : "sometext",
"type" : "notype"
},
"child_vesrion_2" : {
"childName" : "abc",
"createdDate" : "2020-02-25T14:01:58.697Z",
"text" : "sometext2",
"type" : "notype"
},
"active" : "child_vesrion_1"
}
I am trying to get parent detail along with active child version detail. Here i am using aggregation and lookup.
I am constructing "finalList" field by using mongoDB $addFields.
Here is my query;
db.parent
.aggregate([
{
$match: {
'_id' : '5e6c70e8996ddf1c28e14504'
},
},
{
$lookup: {
from: 'chilednodes',
localField: 'child_id',
foreignField: '_id',
as: 'child',
},
},
{
$addFields: {
finalList: {
$map: {
input: '$child',
as: 'c',
in: {
$let: {
vars: { "currentVersionKey": "child_vesrion_1"},
in: {
child_id:'$$c._id',
start_date : '$$c.startDate',
current_version_Key : '$$currentVersionKey',
active_child_name : '$$c.currentVersionKey.childName'
}
}
},
},
},
},
},
{
$project: {
child: 0,
},
},
])
In the response (finalList) i need active child name. I am taking a variable "currentVersionKey" and assigning value as "child_vesrion_1" and using that variable to find the value in "chilednodes". I am not able to get active childname.
NOTE : For testing i have hardcoded "currentVersionKey". But it will be populated dynamically
Here is my expected result;
{
"_id" : "5e6c70e8996ddf1c28e14504",
"startDate" : "2020-02-25T14:01:58.697Z",
"active_id" : "child_vesrion_1",
"child_id" : "5e5e2cd4e972a95b6c32b5bf30",
"finalList" : [
{
"child_id" : "5e5e2cd4e972a95b6c32b5bf30",
"start_date" : "2020-02-25T14:01:58.697Z",
"current_version_Key" : "child_vesrion_1",
"active_child_name" : "xyz"
}
]
}
But i am not getting "active_child_name" : "xyz" in the response. Any helps on this would be appreciated.

You can use $lookup pipeline,
db.parent.aggregate([
{ $match: { "_id": "5e6c70e8996ddf1c28e14504" } },
{
$lookup: {
from: "childnodes",
let: { "child_id": "$child_id", "activeid": "$active_id" },
pipeline: [
{ $match: { "$expr": { $eq: ["$_id", "$$child_id"] } } },
{
$project: {
"child_id": "$_id",
"start_date": "$startDate",
"current_version_Key": "$active",
"active_child_name": {
"$reduce": {
"input": { "$objectToArray": "$$ROOT" },
"initialValue": "",
"in": {
"$cond": [{ "$eq": ["$$this.k", "$$activeid"] },
"$$this.v.childName",
"$$value"
]
}
}
}
}
}
],
as: "finalList",
},
}
])

Related

How to $lookup by avoiding null values in mongodb aggregate

In here i'm using $lookup to to a left join from other collections, the query works fine but when some records missing values it returns
errmsg : $in requires an array as a second argument, found: null
Heres the querying document structure :
{
"no" : "2020921008981",
"sale" : {
"soldItems" : [
{
"itemId" : "5b55ac7f0550de00210a3b24",
},
{
"itemId" : "5b55ac7f0550de00215584re",
}
],
"bills" : [
{
"billNo" : "2020921053467",
"insurancePlanId" : "160",
},
{
"billNo" : "2020921053467",
"insurancePlanId" : "170",
}
],
"visitIds" : [
5b55ac7f0550de00210a3b24, 5b55ac7f0550de00210a3b24
]
}
}
the query :
db.case.aggregate([
{
$lookup: {
from: "insurance",
let: { ipids: "$sale.bill.insurancePlanId" },
pipeline: [
{
$unwind: "$coveragePlans"
},
{
$match: { $expr: { $in: ["$coveragePlans._id", "$$ipids"] } }
},
{
$project: { _id: 0, name: 1 }
}
],
as: "insurances"
}
},
{
$lookup: {
from: "item",
let: { iid: "$salesOrder.purchaseItems.itemRefId" },
pipeline: [
{
$match: {
$expr: {
$in: ["$_id", {
$map: {
input: "$$iid",
in: { $toObjectId: "$$this" }
}
}
]
}
}
}
],
as: "items"
}
}
])
insurance collection :
{
"_id" : ObjectId("5b55aca20550de00210a6d25"),
"name" : "HIJKL"
"coveragePlans" : [
{
"_id" : "160",
"name" : "UVWZ",
},
{
"_id" : "161",
"name" : "LMNO",
}
]
},
{
"_id" : ObjectId("5b55aca20550de00210a6d25"),
"name" : "WXYZ"
"coveragePlans" : [
{
"_id" : "169",
"name" : "5ABC",
},
{
"_id" : "170",
"name" : "4XYZ",
}
]
}
item collection :
{
"_id" : ObjectId("5b55ac7f0550de00210a3b24"),
"code" : "ABCDE"
},
{
"_id" : ObjectId("5b55ac7f0550de00215584re"),
"code" : "PQRST"
}
How to avoid this and do null checks effectively before pipe-lining into the next stages? Tried with { $match: { "fieldName": { $exists: true, $ne: null } } } but it returns mongo error regarding the format. If its the way to go please mention the stage i should put that.. Thanks in advance
You can use $ifNull operator
let: { ipids: {$ifNull:["$sale.bill.insurancePlanId", [] ]} },
EDIT: To skip empty "$salesOrder.purchaseItems.itemRefId" values
let: { iid: {$filter: {input:"$salesOrder.purchaseItems.itemRefId", cond:{$ne:["$$this", ""]}}} },
You can get around that by not using $in.
It looks like this $map is executed separately for every document in the items collection. If you were to run the map in an $addFields stage, you could used the simple form of lookup to match the added field to _id, which would automagically handle missing, null, and array.
Remove the added field with a $project stage if necessary.
db.case.aggregate([
{$lookup: {
from: "insurance",
let: { ipids: "$sale.bill.insurancePlanId" },
pipeline: [
{$unwind: "$coveragePlans"},
{$match: { $expr: { $in: ["$coveragePlans._id", "$$ipids"] } }},
{$project: { _id: 0, name: 1 }}
],
as: "insurances"
}}
{$addFields:{
matchArray:{$map: {
input: "$$iid",
in: { $toObjectId: "$$this" }
}}
}},
{$lookup: {
from: "item",
localField: "matchArray",
foreignField:"_id",
as: "items"
}},
{$project:{
arrayField: 0
}}
])

How to iterate list in mongodb $lookup and pipeline

I have two collections i.e parent and chilednodes.
{
"_id" : "5e6cd8c1996ddf1c28e14505",
"parentList" : [
{
"_id" : "5e6c70e8996ddf1c28e14504",
"startDate" : "2020-02-25T14:01:58.697Z",
"active_id" : "child_vesrion_1",
"child_id" : "5e5e2cd4e972a95b6c32b5bf30"
},
{
"_id" : "5e6c70e8996ddf1c28e14506",
"startDate" : "2020-02-25T14:01:58.697Z",
"active_id" : "child_vesrion_1",
"child_id" : "5e5e2cd4e972a95b6c32b5bf31"
}
]
}
And childnodes are;
{
"_id" : "5e5e2cd4e972a95b6c32b5bf31",
"startDate" : "2020-03-25T14:01:58.697Z",
"endDate" : null,
"child_vesrion_1" : {
"childName" : "test3",
"createdDate" : "2020-02-25T14:01:58.697Z",
"text" : "test3 text",
"type" : "test3 type"
},
"child_vesrion_2" : {
"childName" : "Test4",
"createdDate" : "2020-02-25T14:01:58.697Z",
"text" : "test4 text",
"type" : "test4 type"
},
"active" : "child_vesrion_1"
},
{
"_id" : "5e5e2cd4e972a95b6c32b5bf30",
"startDate" : "2020-02-25T14:01:58.697Z",
"endDate" : null,
"child_vesrion_1" : {
"childName" : "test1",
"createdDate" : "2020-02-25T14:01:58.697Z",
"text" : "test1 text",
"type" : "test1 type"
},
"child_vesrion_2" : {
"childName" : "test2",
"createdDate" : "2020-02-25T14:01:58.697Z",
"text" : "test2 text",
"type" : "test2 type"
},
"active" : "child_vesrion_1"
}
Here is my query;
db.parent.aggregate([
{ $match: { "_id": "5e6cd8c1996ddf1c28e14505" } },
{
$lookup: {
from: "childnodes",
let: { "child_id": "$parentList.child_id", "activeid": "$parentList.active_id" },
pipeline: [
{ $match: { "$expr": { $eq: ["$_id", "$$child_id"] } } },
{
$project: {
"child_id": "$_id",
"start_date": "$startDate",
"current_version_Key": "$active",
"active_child_name": {
"$reduce": {
"input": { "$objectToArray": "$$ROOT" },
"initialValue": "",
"in": {
"$cond": [{ "$eq": ["$$this.k", "$$activeid"] },
"$$this.v.childName",
"$$value"
]
}
}
},
"text": {
"$reduce": {
"input": { "$objectToArray": "$$ROOT" },
"initialValue": "",
"in": {
"$cond": [{ "$eq": ["$$this.k", "$$activeid"] },
"$$this.v.text",
"$$value"
]
}
}
},
"type": {
"$reduce": {
"input": { "$objectToArray": "$$ROOT" },
"initialValue": "",
"in": {
"$cond": [{ "$eq": ["$$this.k", "$$activeid"] },
"$$this.v.type",
"$$value"
]
}
}
}
}
}
],
as: "finalList",
},
},
{
$project: {
parentList: 0,
},
},
]);
I am expecting results like;
{
"_id": "5e6cd8c1996ddf1c28e14505",
"finalList": [
{
"child_id": "5e5e2cd4e972a95b6c32b5bf30",
"start_date": "2020-02-25T14:01:58.697Z",
"current_version_Key": "child_vesrion_1",
"active_child_name": "test1",
"text": "test1 text",
"type": "test1 type",
},
{
"child_id": "5e5e2cd4e972a95b6c32b5bf31",
"start_date": "2020-02-25T14:01:58.697Z",
"current_version_Key": "child_vesrion_1",
"active_child_name": "test3",
"text": "test3 text",
"type": "test3 type",
}
]
}
But i am not getting anything in finalList. It is returning an empty array.
I have tried with different approaches but it didn't help me. I am bit new to mongodb, any help on this would be appreciable.
You were so close. Your parentList is an array, so when you define child_id and activeid inside $lookup, they are also array.
If we add $unwind before the $lookup + $group at the end, your query works as expected.
Try this one:
db.parent.aggregate([
{
$match: {
"_id": "5e6cd8c1996ddf1c28e14505"
}
},
{
$unwind: "$parentList"
},
{
$lookup: {
from: "childnodes",
let: {
"child_id": "$parentList.child_id",
"activeid": "$parentList.active_id"
},
pipeline: [
{
$match: {
"$expr": {
$eq: [
"$_id",
"$$child_id"
]
}
}
},
{
$addFields: {
child_version: {
$arrayElemAt: [
{
$filter: {
input: {
$objectToArray: "$$ROOT"
},
cond: {
$eq: [
"$$this.k",
"$$activeid"
]
}
}
},
0
]
}
}
},
{
$project: {
"_id": 0,
"child_id": "$_id",
"start_date": "$startDate",
"current_version_Key": "$active",
"active_child_name": "$child_version.v.childName",
"text": "$child_version.v.text",
"type": "$child_version.v.type"
}
}
],
as: "finalList"
}
},
{
$unwind: "$finalList"
},
{
$group: {
_id: "$_id",
parentList: {
$push: "$finalList"
}
}
}
])
MongoPlayground

How to aggregate lookup sub array documents in mongoDB, and projecting the result?

I have 2 Collections
Posts
Users
Posts collection contains comments array which stores { userId, comment } object, along with other information.
users ollection contains user's information.
I want to return the complete result.
Ex:
{
"postId":"xvzeee",
"post": "Good Morning",
"likedBy":[
12342234,
23456534
]
"comments": [
{
"comment": "very good morning",
"userName": "Max"
},
{
"comment": "v. GM",
"userName": "Suraj"
}
]
}
My Approach to achieve the above result is.
db.wall.aggregate([
{ $lookup: { from: 'profiles', localField: 'likedBy', foreignField: 'profileId', as: 'likedBy' } },
{ $lookup: { from: 'profiles', localField: 'comments.commentedBy', foreignField: 'profileId', as: 'commentedUser' } },
{
$project:{
"likedBy.name": 1,
"likedBy.profileId": 1,
createdBy: 1,
createdAt: 1,
updatedAt: 1,
comments : [{
comment: "$comments.comment",
user: "$commentedUser.name"
}],
"commentedUser.name" : 1
}
}
])
The result is coming like below:
{
"_id" : ObjectId("5dfdbb129f644213c413eb18"),
"likedBy" : [
{
"profileId" : "96444206",
"name" : "Vinay3"
},
{
"profileId" : "400586806",
"name" : "Dev"
}
],
"createdBy" : "96444206",
"commentedUser" : [
{
"name" : "Vinay3"
},
{
"name" : "Dev"
}
],
/*Facing problem in comment array*/
"comments" : [
{
"comment" : [
"Super-awesome",
"FAB",
],
"user" : [
"Vinay3",
"Dev"
]
}
]
}
The comment should look like :
[{
...
"comments" : [
{
"comments" : [
{
comment :"Super-awesome",
user: "Vinay3",
profileId: "11111..."
},
{
comment: "FAB",
user: "Dev",
profileId: "2222..."
}
],
}
]
}]
The Posts Collection looks like this :
[{
"_id" : ObjectId("5dfdbb129f699913c413eb18"),
"post":"Good Morning",
"createdBy" : "96444206",
"postId" : "D9644s5h8m",
"likedBy" : [
"96444206",
"40058680"
],
"comments" : [
{
"commentId" : "COM9644",
"commentedBy" : "96444206",
"comment" : "Super-awesome"
},
{
"commentId" : "COM9644",
"commentedBy" : "96444206",
"comment" : "#FAB"
},
{
"commentId" : "COM00587",
"commentedBy" : "400586806",
"comment" : "marvelous"
}
],
"createdAt" : ISODate("2019-12-21T11:56:26.944+05:30"),
"updatedAt" : ISODate("2019-12-21T12:12:35.047+05:30"),
"__v" : 0
}, {...}, {...}]
User Profiles Collection
[{
"_id" : ObjectId("5dd4ff3abe53181160efa446"),
"accountStatus" : "CONFIRMED",
"profileId" : "400586806",
"name" : "Dev",
"email" : "dev#xyz.com",
"createdAt" : ISODate("2019-11-20T14:24:18.692+05:30"),
"updatedAt" : ISODate("2019-12-20T16:58:06.041+05:30"),
"__v" : 0
}, {...}, {...} ]
How to achieve this, any help will much be appreciated.
However, I'm able to give a solution to my problem like below.
If there any better solution than this will much be appreciated.
db.wall.aggregate([
{ $unwind: '$comments'},
{ $lookup: { from: 'profiles', localField: 'comments.commentedBy', foreignField: 'profileId', as: 'comments.user' } },
{ $unwind: '$comments.user' },
{
$group: {
_id:'$_id',
postId: { $first: "$postId"},
likedBy: { $first: "$likedBy"},
createdBy: { $first: '$createdBy'},
comments: { $push : '$comments' },
createdAt: { $first: "$createdAt" },
updatedAt: { $first: "$updatedAt" },
}
},{
$project: {
_id:1,
postId: 1,
"likedBy.name": 1,
"likedBy.profileId": 1,
createdBy: 1,
comments: {
$map : {
input: '$comments',
as: 'com',
in: {
commentId: "$$com.commentId",
comment: "$$com.comment",
name: "$$com.user.name"
}
}
},
createdAt: 1,
updatedAt: 1,
}
}
])
I want to add isActive => true || false field to the comments object.
now the challenge is how to filter only isActive => true comments ?
Here is my approach
db.posts.aggregate([
{
$unwind: '$likedBy',
},
{
$unwind: '$comments',
},
{
$lookup: {
from: 'users',
localField: 'likedBy',
foreignField: 'profileId',
as: 'likedByUser'
},
},
{
$unwind: '$likedByUser'
},
{
$lookup: {
from: 'users',
localField: 'comments.commentedBy',
foreignField: 'profileId',
as: 'commentByUser'
},
},
{
$unwind: '$commentByUser'
},
{
$group: {
"_id": '$postId',
"post": { $first: 'post'} ,
comments: {
$push: {
"commentId": "$comments.commentId",
"commentedBy": "$likedByUser.name",
"comment": "$comments.comment"
}
},
likes: {
$push: {
"likedByName": "$likedByUser.name",
"likeById": "$likedBy"
}
}
}
},
{
$project: {
"_id": 0,
"postId":'$_id',
"post": 1,
"comments": 1,
"likes": 1
}
}
])

Rewind data of two nested array field after $unwind and $lookup and $filter on date range in $project

{
"_id" : ObjectId("590b12b6330e1567acd29e69"),
"name": "Foo",
"sales_history" : [
{
"_id" : ObjectId("593ce8e4cfaa652df543d9e3"),
"sold_at" : ISODate("2017-06-11T06:53:24.881Z"),
"sold_to" : ObjectId("593509e938792e046ba14a02"),
"sold_products" : [
{
"product_dp" : 100,
"quantity" : 1,
"product_id" : ObjectId("591068be1f4c6c79a442a788"),
"_id" : ObjectId("593ce8e4cfaa652df543d9e5")
},
{
"product_dp" : 100,
"quantity" : 1,
"product_id" : ObjectId("593a33dccfaa652df543d924"),
"_id" : ObjectId("593ce8e4cfaa652df543d9e4")
}
]
},
{
"_id" : ObjectId("5944cb7142a04740357020b9"),
"sold_at" : ISODate("2017-06-17T06:25:53.332Z"),
"sold_to" : ObjectId("5927d4a59e58ba0c61066f3b"),
"sold_products" : [
{
"product_dp" : 500,
"quantity" : 1,
"price" : 5650,
"product_id" : ObjectId("593191ed53a2741dd9bffeb5"),
"_id" : ObjectId("5944cb7142a04740357020ba")
}
]
}
]
}
I have User schema like this. I want detail of product_id reference, with a date range search criteria on sold_at date field.
My expected data like following when I searched in sold_at at: 2017-06-11
{
"_id" : ObjectId("590b12b6330e1567acd29e69"),
"name": "Foo",
"sales_history" : [
{
"_id" : ObjectId("593ce8e4cfaa652df543d9e3"),
"sold_at" : ISODate("2017-06-11T06:53:24.881Z"),
"sold_to" : ObjectId("593509e938792e046ba14a02"),
"sold_products" : [
{
"product_dp" : 100,
"quantity" : 1,
"product_id": {
_id:ObjectId("hsfgg123412yh3gy1u2g3"),
name: "Product1",
code: "FG0154"
},
}
]
}
]
}
Product detail need to be populate in product_id, sales_history array need to be filtered in date range.
You can try below aggregation query.
$filter sales history on date range followed by $unwinding sales history & sold_products.
$lookup sold_products to get the product details.
$group back sold_products & sales history
db.collection.aggregate([
{
"$project": {
"name": 1,
"sales_history": {
"$filter": {
"input": "$sales_history",
"as": "history",
"cond": {
"$and": [
{
"$gte": [
"$$history.sold_at",
ISODate("2017-06-11T00:00:00.000Z")
]
},
{
"$lt": [
"$$history.sold_at",
ISODate("2017-06-12T00:00:00.000Z")
]
}
]
}
}
}
}
},
{
"$unwind": "$sales_history"
},
{
"$unwind": "$sales_history.sold_products"
},
{
"$lookup": {
"from": lookupcollection,
"localField": "sales_history.sold_products.product_id",
"foreignField": "_id",
"as": "sales_history.sold_products.product_id"
}
},
{
"$group": {
"_id": {
"_id": "$_id",
"sales_history_id": "$sales_history._id"
},
"name": {
"$first": "$name"
},
"sold_at": {
"$first": "$sales_history.sold_at"
},
"sold_to": {
"$first": "$sales_history.sold_to"
},
"sold_products": {
"$push": "$sales_history.sold_products"
}
}
},
{
"$group": {
"_id": "$_id._id",
"name": {
"$first": "$name"
},
"sales_history": {
"$push": {
"_id": "$_id.sales_history_id",
"sold_at": "$sold_at",
"sold_to": "$sold_to",
"sold_products": "$sold_products"
}
}
}
}
]);

MongoDB join data inside an array of objects

I have document like this in a collection called diagnoses :
{
"_id" : ObjectId("582d43d18ec3f432f3260682"),
"patientid" : ObjectId("582aacff3894c3afd7ad4677"),
"doctorid" : ObjectId("582a80c93894c3afd7ad4675"),
"medicalcondition" : "high fever, cough, runny nose.",
"diagnosis" : "Viral Flu",
"addmissiondate" : "2016-01-12",
"dischargedate" : "2016-01-16",
"bhtno" : "125",
"prescription" : [
{
"drug" : ObjectId("58345e0e996d340bd8126149"),
"instructions" : "Take 2 daily, after meals."
},
{
"drug" : ObjectId("5836bc0b291918eb42966320"),
"instructions" : "Take 1 daily, after meals."
}
]
}
The drug id inside the prescription object array is from a separate collection called drugs, see sample document below :
{
"_id" : ObjectId("58345e0e996d340bd8126149"),
"genericname" : "Paracetamol Tab 500mg",
"type" : "X",
"isbrand" : false
}
I am trying to create a mongodb query using the native node.js driver to get a result like this:
{
"_id" : ObjectId("582d43d18ec3f432f3260682"),
"patientid" : ObjectId("582aacff3894c3afd7ad4677"),
"doctorid" : ObjectId("582a80c93894c3afd7ad4675"),
"medicalcondition" : "high fever, cough, runny nose.",
"diagnosis" : "Viral Flu",
"addmissiondate" : "2016-01-12",
"dischargedate" : "2016-01-16",
"bhtno" : "125",
"prescription" : [
{
"drug" :
{
"_id" : ObjectId("58345e0e996d340bd8126149"),
"genericname" : "Paracetamol Tab 500mg",
"type" : "X",
"isbrand" : false
},
"instructions" : "Take 2 daily, after meals."
},
...
]
}
Any advice on how to approach a similar result like this is much appreciated, thanks.
Using MongoDB 3.4.4 and newer
With the aggregation framework, the $lookup operators supports arrays
db.diagnoses.aggregate([
{ "$addFields": {
"prescription": { "$ifNull" : [ "$prescription", [ ] ] }
} },
{ "$lookup": {
"from": "drugs",
"localField": "prescription.drug",
"foreignField": "_id",
"as": "drugs"
} },
{ "$addFields": {
"prescription": {
"$map": {
"input": "$prescription",
"in": {
"$mergeObjects": [
"$$this",
{ "drug": {
"$arrayElemAt": [
"$drugs",
{
"$indexOfArray": [
"$drugs._id",
"$$this.drug"
]
}
]
} }
]
}
}
}
} },
{ "$project": { "drugs": 0 } }
])
For older MongoDB versions:
You can create a pipeline that first flattens the prescription array using the $unwind operator and a $lookup subsequent pipeline step to do a "left outer join" on the "drugs" collection. Apply another $unwind operation on the created array from the "joined" field. $group the previously flattened documents from the first pipeline where there $unwind operator outputs a document for each element in the prescription array.
Assembling the above pipeline, run the following aggregate operation:
db.diagnoses.aggregate([
{
"$project": {
"patientid": 1,
"doctorid": 1,
"medicalcondition": 1,
"diagnosis": 1,
"addmissiondate": 1,
"dischargedate": 1,
"bhtno": 1,
"prescription": { "$ifNull" : [ "$prescription", [ ] ] }
}
},
{
"$unwind": {
"path": "$prescription",
"preserveNullAndEmptyArrays": true
}
},
{
"$lookup": {
"from": "drugs",
"localField": "prescription.drug",
"foreignField": "_id",
"as": "prescription.drug"
}
},
{ "$unwind": "$prescription.drug" },
{
"$group": {
"_id": "$_id",
"patientid" : { "$first": "$patientid" },
"doctorid" : { "$first": "$doctorid" },
"medicalcondition" : { "$first": "$medicalcondition" },
"diagnosis" : { "$first": "$diagnosis" },
"addmissiondate" : { "$first": "$addmissiondate" },
"dischargedate" : { "$first": "$dischargedate" },
"bhtno" : { "$first": "$bhtno" },
"prescription" : { "$push": "$prescription" }
}
}
])
Sample Output
{
"_id" : ObjectId("582d43d18ec3f432f3260682"),
"patientid" : ObjectId("582aacff3894c3afd7ad4677"),
"doctorid" : ObjectId("582a80c93894c3afd7ad4675"),
"medicalcondition" : "high fever, cough, runny nose.",
"diagnosis" : "Viral Flu",
"addmissiondate" : "2016-01-12",
"dischargedate" : "2016-01-16",
"bhtno" : "125",
"prescription" : [
{
"drug" : {
"_id" : ObjectId("58345e0e996d340bd8126149"),
"genericname" : "Paracetamol Tab 500mg",
"type" : "X",
"isbrand" : false
},
"instructions" : "Take 2 daily, after meals."
},
{
"drug" : {
"_id" : ObjectId("5836bc0b291918eb42966320"),
"genericname" : "Paracetamol Tab 100mg",
"type" : "Y",
"isbrand" : false
},
"instructions" : "Take 1 daily, after meals."
}
]
}
In MongoDB 3.6 or later versions
It seems that
$lookup will overwrite the original array instead of merging it.
A working solution (a workaround, if you prefer) is to create a different field,
and then merge two fields, as shown below:
db.diagnoses.aggregate([
{ "$lookup": {
"from": "drugs",
"localField": "prescription.drug",
"foreignField": "_id",
"as": "prescription_drug_info"
} },
{ "$addFields": {
"merged_drug_info": {
"$map": {
"input": "$prescription",
"in": {
"$mergeObjects": [
"$$this",
{ "$arrayElemAt": [
"$prescription_drug_info._id",
"$$this._id"
] }
]
}
}
}
} }
])
This would add two more fields and the name of the desired field
will be merged_drug_info. We can then add $project stage to filter
out excessive fields and $set stage to rename the field:
...
{ "$set": { "prescription": "$merged_drug_info" } },
{ "$project": { "prescription_drug_info": 0, "merged_drug_info": 0 } }
...