MongoDB将数据连接到一个对象数组中

时间:2016-12-06 09:39:16

标签: mongodb mongodb-query aggregation-framework nosql

我在一个名为诊断

的集合中有这样的文档
pg_dump

处方对象数组中的药物 ID来自名为药物的单独集合,请参阅下面的示例文档:

Picasso.with(context)
.load(url)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.networkPolicy(NetworkPolicy.NO_CACHE)
.fit()
.placeholder(YOUR PLACE HOLDER RESOURCE)
.centerCrop()
.into(imageView);

我正在尝试使用native node.js驱动程序创建一个mongodb查询,以获得如下结果:

   {
        "_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."
            }
        ]
    }

非常感谢任何有关如何处理类似结果的建议,谢谢。

2 个答案:

答案 0 :(得分:7)

使用MongoDB 3.4.4及更新版

使用聚合框架, $lookup 运算符支持数组

db.diagnoses.aggregate([
    { "$addFields": { 
        "prescription": { "$ifNull" : [ "$prescription", [ ] ] }    
    } },
    { "$lookup": {
        "from": "drugs",
        "localField": "prescription.drug",
        "foreignField": "_id",
        "as": "prescription.drug"
    } }
])

对于较旧的MongoDB版本:

您可以使用 $unwind 运算符和 $lookup 后续管道步骤创建首先展平prescription数组的管道做一个"左外连接"关于"药物"采集。从"加入"对已创建的数组应用另一个 $unwind 操作领域。 $group 来自第一个管道的先前展平的文档,其中 $unwind 运算符为处方数组中的每个元素输出文档。

组装上述管道,运行以下聚合操作:

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" }
        }
    }
])

示例输出

{
    "_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."
        }
    ]
}

答案 1 :(得分:1)

在MongoDB 3.6或更高版本中

似乎 $lookup将覆盖原始数组,而不是合并它。 一个可行的解决方案(如果您愿意,可以采用一种解决方法)是创建一个不同的字段, 然后合并两个字段,如下所示:

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"
                        ] }
                    ] 
                }
            }
        }
    } }
])

这将再添加两个字段和所需字段的名称 将为merged_drug_info。然后,我们可以添加$project阶段进行过滤 删除多余的字段,并$set阶段重命名该字段:

...
{ "$set": { "prescription": "$merged_drug_info" } },
{ "$project": { "prescription_drug_info": 0, "merged_drug_info": 0 } }
...