MongoDB join data inside an array of objects

后端 未结 2 1967
无人共我
无人共我 2020-12-30 09:21

I have document like this in a collection called diagnoses :

   {
        \"_id\" : ObjectId(\"582d43d18ec3f432f3260682\"),
        \"patien         


        
相关标签:
2条回答
  • 2020-12-30 09:42

    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": "prescription.drug"
        } }
    ])
    

    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."
            }
        ]
    }
    
    0 讨论(0)
  • 2020-12-30 09:52

    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 } }
    ...
    
    0 讨论(0)
提交回复
热议问题