MongoDB聚合合并条件

问题描述 投票:0回答:1

我有下面的集合,我使用 MongoDB 聚合来实现输出(其中我聚合订单的所有订单行项目)并尝试合并到另一个集合中(

order
)。

[
  {
    "order_line_item_id": 1,
    "order_id": 100,
    "products": [
      {
        "name": "Shoe",
        "hasDefect": "YES"
      },
      {
        "name": "Pant",
        "hasDefect": "NO"
      },
      {
        "name": "Shirt",
        "hasDefect": "NOT_SURE"
      }
    ]
  },
  {
    "order_line_item_id": 2,
    "order_id": 100,
    "products": [
      {
        "name": "Shoe",
        "hasDefect": "YES"
      },
      {
        "name": "Pant",
        "hasDefect": "YES"
      },
      {
        "name": "Shirt",
        "hasDefect": "YES"
      }
    ]
  },
  {
    "order_line_item_id": 3,
    "order_id": 101,
    "products": [
      {
        "name": "Shoe",
        "hasDefect": "YES"
      },
      {
        "name": "Pant",
        "hasDefect": "NO"
      },
      {
        "name": "Shirt",
        "hasDefect": "NOT_SURE"
      }
    ]
  }
]

我使用下面的聚合来实现输出

db.collection.aggregate([
  {
    $match: {
      order_id: {
        $eq: 100
      }
    }
  },
  {
    $unwind: "$products"
  },
  {
    $match: {
      "products.name": {
        $eq: "Pant"
      }
    }
  },
  {
    $group: {
      _id: {
        order_id: "$order_id",
        productName: "$products.name"
      },
      hasDefects: {
        $push: "$products.hasDefect"
      },
      products: {
        $push: "$products"
      }
    }
  },
  {
    $set: {
      hasDefect: {
        $switch: {
          branches: [
            {
              case: {
                $allElementsTrue: {
                  $map: {
                    input: "$hasDefects",
                    as: "d",
                    in: {
                      $eq: [
                        "$$d",
                        "YES"
                      ]
                    }
                  }
                }
              },
              then: "YES"
            },
            {
              case: {
                $in: [
                  "NO",
                  "$hasDefects"
                ]
              },
              then: "NO"
            },
            {
              case: {
                $in: [
                  "NOT_SURE",
                  "$hasDefects"
                ]
              },
              then: "NOT_SURE"
            }
          ],
          default: "<DEFAULT>"
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id.order_id",
      order_id: {
        "$first": "$_id.order_id"
      },
      products: {
        $push: {
          name: "$_id.productName",
          hasDefect: "$hasDefect",
          lastModified: {
            $dateToString: {
              date: new Date(),
              timezone: "America/New_York"
            }
          }
        }
      }
    }
  },
  {
    $unset: [
      "_id"
    ]
  },
  { 
    $merge: { 
      into: "order_res", 
      on: [ "order_id" ], 
      whenMatched: "replace", 
      whenNotMatched: "insert" 
    }
  }
])

输出可以是一个新文档,也可以是

order
文档中某个产品的更新(如下所示)。

[
  {    
    "order_id": 100,
    "products": [
      {
        "name": "Shoe",
        "hasDefect": "YES"
      },
    ]
  }
]   

我正在使用合并聚合阶段插入/更新到另一个 mongoDB 集合。

{ $merge: { into: "order", on: "order_id", whenMatched: "replace", whenNotMatched: "insert" }}

问题是这是一项更新操作,并且订单包含以前的产品,它会用这个新产品替换所有现有产品。 例如,如果订单有以下文档,则应仅更新“鞋”产品。

[
  {    
    "order_id": 100,
    "products": [
      {
        "name": "Shoe",
        "hasDefect": "NO"
      },
      {
        "name": "Pant",
        "hasDefect": "NO"
      },
      {
        "name": "Shirt",
        "hasDefect": "NOT_SURE"
      }
    ]
  }
]
mongodb aggregation-framework
1个回答
0
投票

您可以使用 $mergeObjects 代替 $merge 来创建包含所需文档的新集合。 请告诉我以下查询是否适合您:

[
  {
    $match: {
      order_id: 100
    }
  },
  {
    $unwind: "$products"
  },
  {
    $match: {
      "products.name": "Pant"
    }
  },
  {
    $group: {
      _id: {
        order_id: "$order_id",
        productName: "$products.name"
      },
      hasDefects: {
        $push: "$products.hasDefect"
      }
    }
  },
  {
    $set: {
      hasDefect: {
        $switch: {
          branches: [
            {
              case: {
                $allElementsTrue: {
                  $map: {
                    input: "$hasDefects",
                    as: "d",
                    in: {
                      $eq: ["$$d", "YES"]
                    }
                  }
                }
              },
              then: "YES"
            },
            {
              case: {
                $in: ["NO", "$hasDefects"]
              },
              then: "NO"
            },
            {
              case: {
                $in: ["NOT_SURE", "$hasDefects"]
              },
              then: "NOT_SURE"
            }
          ],
          default: "<DEFAULT>"
        }
      }
    }
  },
  {
    $project: {
      order_id: "$_id.order_id",
      productName: "$_id.productName",
      hasDefect: "$hasDefect",
      lastModified: {
        $dateToString: {
          date: new Date(),
          timezone: "America/New_York"
        }
      }
    }
  },
  {
    $merge: {
      into: "order",
      whenMatched: [
        {
          $addFields: {
            products: {
              $map: {
                input: "$$ROOT.products",
                as: "product",
                in: {
                  $cond: {
                    if: {
                      $eq: ["$$product.name", "$productName"]
                    },
                    then: {
                      $mergeObjects: [
                        "$$product",
                        { hasDefect: "$hasDefect" }
                      ]
                    },
                    else: "$$product"
                  }
                }
              }
            }
          }
        }
      ],
      whenNotMatched: "insert"
    }
  }
]

致以诚挚的问候 阿萨瓦里

© www.soinside.com 2019 - 2024. All rights reserved.