匹配并将新字段添加到Mongodb聚合中的每个数组元素

时间:2020-09-17 15:16:38

标签: mongodb mongodb-query aggregation-framework spring-data-mongodb

我下面有两个集合,我正在通过聚合和合并来创建视图表。

account table:
{
    "_id": {
        "$oid": "5f61b573db16185cebfeaaf9"
    },
    "status": "ACTIVE",
    "personalInfo": {
        "entityName": "John Doe",
        ...
    },
    "createdDateTime": {
        "$date": "2020-09-16T06:49:23.103Z"
    },
    "modifiedDateTime": {
        "$date": "2020-09-16T06:49:23.103Z"
    }
}

account_transactions:
{
    "_id": {
        "$oid": "5f61b5b3db16185cebfeab0c"
    },
    "accountId": "5f61b573db16185cebfeaaf9",
    "transactionType": "Payment",
    "transactionStatus": "NEW",
    "createdDate": {
        "$date": "2020-09-16T06:50:27.305Z"
    },
    "createdBy": "sujal.shakya@joinsage.com",
    "lastModifiedDate": {
        "$date": "2020-09-16T10:23:06.617Z"
    }
}

{
    "_id": {
        "$oid": "5f61b5b3db16185cebfeab0f"
    },
    "accountId": "5f61b573db16185cebfeaaf9",
    "transactionType": "Credit",
    "createdDate": {
        "$date": "2020-09-16T06:50:27.305Z"
    },
    "createdBy": "sujal.shakya@joinsage.com",
    "lastModifiedDate": {
        "$date": "2020-09-16T10:23:06.617Z"
    }
}

在mongodb查询下面,将创建一个视图表,其中每个帐户都有多个交易(如果存在),如果不存在交易,则向其中添加虚拟交易以及一些虚拟字段。

db.account.aggregate(
    [
        {
            $match: {
                'status': 'ACTIVE'
            }
        },

        {$addFields: {"accountId": {"$toString": "$_id"}}},

        {
            $lookup: {
                from: "account_transactions",
                localField: "accountId",
                foreignField: "accountId",
                as: "transactions"
            }
        },
        {
            "$project": {
                "accountType": 1,
                "transactions": {
                    "$cond": [
                        { "$eq": [ "$transactions", [] ] },
                        {$concatArrays: [[{"lastModifiedDate": {$arrayElemAt: ["$account.modifiedDateTime",0]}, "transactionType" : "BLANK"}]] },//adds dummy fields
                        {"$filter": {
                        "input": "$transactions",
                        "as": "transactions",
                        "cond": {
                            "$or": [
                                {
                                    "$eq": [
                                        "$$transactions.transactionType",
                                        "Payment"
                                    ]
                                },
                                {
                                    "$eq": [
                                        "$$transactions.transactionType",
                                        "Sale"
                                    ]
                                },
                                {
                                    "$eq": [
                                        "$$transactions.transactionType",
                                        "Debit"
                                    ]
                                }

                            ]
                        }
                    }
                    }
                },
                "createdBy": 1
            }
        },
        {$merge: {into: "account_view_table", on: "_id", whenMatched: "replace", whenNotMatched: "insert"}}
    ])

我现在要做的是在上面为每个交易通过匹配交易类型创建的视图表中添加一个新字段。例如:如果一个帐户有多个交易,每个交易具有不同的交易类型,则检查每个交易的transactionType并在每个交易上添加新字段“ transactionTypeOrder ”:

我一直在尝试不同的方法,但是没有任何作用

 {$addFields: {"transactions.transactionTypeOrder" : 
             {
                 $cond: [{$in:["$transactions.transactionType",["Payment"]]},"1",
                     {$cond: [ {$in:["$transactions.transactionType",["Sale"]]},"2",
                             {$cond: [{$in:["$transactions.transactionType",["Debit"]]},"3", "4" ]}
                             ]}
                             ]
             }
 }},

因此,如果transactionType ==“ Payment”添加transactionTypeOrder:1,如果transactionType ==“ Sales”添加transactionTypeOrder:2等。我正在寻找的输出如下:

第二种情况下,还要检查另一个字段: 在同一笔交易中,我还必须对其他字段进行另一次检查,以检查“ transactionStatus”字段是否存在,如果不存在,则将“ transactionStatusOrderAsc”字段添加为“ ####”,将“ transactionStatusOrderDsc”添加为“ ~~~”,如果存在与“ transactionStatus”相同的值,那么输出将如下所示:

所以基本上,我必须检查transactionType并添加新的Filed,同时还要检查transactionStatus和两个需求字段。

 //result view table
        {
            "_id": {
                "$oid": "5f61b573db16185cebfeaafd"
            },
            //...other fields.
            "transactions": [{
                "transactionType": "Payment",
                "transactionTypeOrder": 1,
                "transactionStatus": "New",
                "transactionStatusOrderAsc": "New",
                "transactionStatusOrderDsc": "New"
            },
        
            {
                "transactionType": "Sales",
                "transactionTypeOrder": 2,
                "transactionStatusOrderAsc": "####", //since transactionStatus field doesn't exist here
                "transactionStatusOrderDsc": "~~~~"
            },
        
            {
                "transactionType": "Debit",
                "transactionTypeOrder": 3,
                "transactionStatus": "Old",
                "transactionStatusOrderAsc": "Old",
                "transactionStatusOrderDsc": "Old"
            }
        
            ]
        }

1 个答案:

答案 0 :(得分:2)

您可以使用from here来应用数组的每个元素,并使用$map来检查值并添加字段。

db.account.aggregate([
  {
    $match: {
      "status": "ACTIVE"
    }
  },
  {
    $addFields: {
      "accountId": {
        "$toString": "$_id"
      }
    }
  },
  {
    $lookup: {
      from: "account_transactions",
      localField: "accountId",
      foreignField: "accountId",
      as: "transactions"
    }
  },
  {
    "$project": {
      "accountType": 1,
      "createdBy": 1,
      transactions: /**adds dummy fields*/
      {
        "$map": {
          "input": "$transactions",
          "as": "transactions",
          "in": {
            $switch: {
              branches: [
                {
                  case: {
                    $eq: [
                      "$$transactions.transactionType",
                      "Payment"
                    ]
                  },
                  then: {
                    transactionType: "$$transactions.transactionType",
                    transactionTypeOrder: 1
                  }
                },
                {
                  case: {
                    $eq: [
                      "$$transactions.transactionType",
                      "Sales"
                    ]
                  },
                  then: {
                    transactionType: "$$transactions.transactionType",
                    transactionTypeOrder: 2
                  }
                },
                {
                  case: {
                    $eq: [
                      "$$transactions.transactionType",
                      "Debit"
                    ]
                  },
                  then: {
                    transactionType: "$$transactions.transactionType",
                    transactionTypeOrder: 3
                  }
                },
                
              ],
              default: {
                transactionType: "$$transactions.transactionType",
                transactionTypeOrder: -1
              }
            }
          }
        }
      }
    }
  },
])

如果您需要每个事务的其他字段,则必须在每种情况下添加它们。 您可以对其进行测试$switch


第一次评论编辑

如果必须包括所有交易字段,则可以使用here而不是手动创建对象。

db.account.aggregate([
  {
    $match: {
      "status": "ACTIVE"
    }
  },
  {
    $addFields: {
      "accountId": {
        "$toString": "$_id"
      }
    }
  },
  {
    $lookup: {
      from: "account_transactions",
      localField: "accountId",
      foreignField: "accountId",
      as: "transactions"
    }
  },
  {
    "$project": {
      "accountType": 1,
      "createdBy": 1,
      transactions: /**adds dummy fields*/
      {
        "$map": {
          "input": "$transactions",
          "as": "transactions",
          "in": {
            $switch: {
              branches: [
                {
                  case: {
                    $eq: [
                      "$$transactions.transactionType",
                      "Payment"
                    ]
                  },
                  then: {
                    $mergeObjects: [
                      "$$transactions",
                      {
                        transactionTypeOrder: 1
                      }
                    ]
                  }
                },
                {
                  case: {
                    $eq: [
                      "$$transactions.transactionType",
                      "Sales"
                    ]
                  },
                  then: {
                    $mergeObjects: [
                      "$$transactions",
                      {
                        transactionTypeOrder: 2
                      }
                    ]
                  }
                },
                {
                  case: {
                    $eq: [
                      "$$transactions.transactionType",
                      "Debit"
                    ]
                  },
                  then: {
                    $mergeObjects: [
                      "$$transactions",
                      {
                        transactionTypeOrder: 3
                      }
                    ]
                  }
                },
                
              ],
              default: {
                $mergeObjects: [
                  "$$transactions",
                  {
                    transactionTypeOrder: -1
                  }
                ]
              }
            }
          }
        }
      }
    }
  },
])

$mergeObjects