加入两个数组的相关属性

时间:2017-07-26 13:57:07

标签: mongodb mongodb-query aggregation-framework

我有以下结果。在下面可以制作一个地图连接数组,每个地图都带有objectid。

{
    "_id": ObjectId("597233b50e717e0585dbd94a"),
    "createdAt": ISODate("2017-07-21T17:02:45.119+0000"),
    "name": "cardoso",
    "gender": "female",
    "profile": [{
            "profession": "master",
            "_id": ObjectId("597233b50e717e0585dbd94b"),
            "departament": ObjectId("597233b50e717e0585dbd94e")
        },
        {
            "_id": ObjectId("59766719003e7d552fe40e8c"),
            "profession": "master",
            "departament": ObjectId("59766719003e7d552fe40e8b")
        },
        {
            "_id": ObjectId("5976b8f99d8a4326c6bf1ae5"),
            "profession": "master",
            "departament": ObjectId("5974d8fe398e5b2fd433410f")
        }
    ],
    "Institution": {
        "_id": ObjectId("597233b50e717e0585dbd94c"),
        "cnpj": 64837134000144.0,
        "deletedAt": false,
        "departament": [{
                "title": "cardoso",
                "category": "Sub-17",
                "_id": ObjectId("597233b50e717e0585dbd94e")
            },
            {
                "sport": "Tênis",
                "title": "novo",
                "category": "Sub-12",
                "_id": ObjectId("59766719003e7d552fe40e8b")
            },
            {
                "_id": ObjectId("5974d8fe398e5b2fd433410f"),
                "category": "Intercâmbio",
                "title": "testeJJJ",
                "sport": "natação"
            }
        ]
    }
}

我需要做以下结果。我不想在节点中操纵结果。

{
    "sport": "Tênis",
    "profession": "master",
    "title": "novo",
    "category": "Sub-12",
    "_id": ObjectId("59766719003e7d552fe40e8b")
}

我已经倾向于做一些事情,但查询最终变得非常大

1 个答案:

答案 0 :(得分:1)

这里的基本前提是在通过$map.进行处理时“查找”其他数组中的内容

这可以通过$indexOfArray使用MongoDB 3.4完成:

db.collection.aggregate([
  { "$addFields": {
    "Institution": {
      "departament": {
        "$map": {
          "input": "$Institution.departament",
          "as": "d",
          "in": {
            "sport": "$$d.title",
            "profession": {
              "$arrayElemAt": [
                "$profile.profession",
                { "$indexOfArray": [ "$profile.departament", "$$d._id" ] }
              ]    
            },
            "title": "$$d.title",
            "category": "$$d.category"   
          } 
        }
      }
    }    
  }}
])

在第一个索引中,我们从"profile"数组中查找与指定字段上的_id的当前值匹配的“索引位置”。然后通过$arrayElemAt提取该索引处的数据。

或使用$filter$arrayElemAt“反过来”使用MongoDB 3.2:

db.collection.aggregate([
  { "$addFields": {
    "Institution": {
      "departament": {
        "$map": {
          "input": "$Institution.departament",
          "as": "d",
          "in": {
            "sport": "$$d.title",
            "profession": {
              "$arrayElemAt": [
                { "$map": {
                  "input": {
                    "$filter": {
                      "input": "$profile",
                      "as": "p",
                      "cond": { "$eq": [ "$$p.departament", "$$d._id" ] }                    
                    }
                  },
                  "as": "p",
                  "in": "$$p.profession"
                }},
                0
              ]
            },
            "title": "$$d.title",
            "category": "$$d.category"   
          } 
        }
      }
    }    
  }}
])

在这种情况下,$filter会将"profile"中的数组内容缩减为仅匹配的元素,这些元素应该只有一个。然后通过$arrayElemAt0索引处提取此内容。

两种情况都有相同的结果:

{
    "_id" : ObjectId("597233b50e717e0585dbd94a"),
    "createdAt" : ISODate("2017-07-21T17:02:45.119Z"),
    "name" : "cardoso",
    "gender" : "female",
    "profile" : [ 
        {
            "profession" : "master",
            "_id" : ObjectId("597233b50e717e0585dbd94b"),
            "departament" : ObjectId("597233b50e717e0585dbd94e")
        }, 
        {
            "_id" : ObjectId("59766719003e7d552fe40e8c"),
            "profession" : "master",
            "departament" : ObjectId("59766719003e7d552fe40e8b")
        }, 
        {
            "_id" : ObjectId("5976b8f99d8a4326c6bf1ae5"),
            "profession" : "master",
            "departament" : ObjectId("5974d8fe398e5b2fd433410f")
        }
    ],
    "Institution" : {
        "_id" : ObjectId("597233b50e717e0585dbd94c"),
        "cnpj" : 64837134000144.0,
        "deletedAt" : false,
        "departament" : [ 
            {
                "sport" : "cardoso",
                "profession" : "master",
                "title" : "cardoso",
                "category" : "Sub-17"
            }, 
            {
                "sport" : "novo",
                "profession" : "master",
                "title" : "novo",
                "category" : "Sub-12"
            }, 
            {
                "sport" : "testeJJJ",
                "profession" : "master",
                "title" : "testeJJJ",
                "category" : "Intercâmbio"
            }
        ]
    }
}