【问题标题】:Add a field with increasing value in MongoDB Aggregation based on condition根据条件在MongoDB聚合中添加一个值增加的字段
【发布时间】:2020-06-19 19:19:38
【问题描述】:

我的收藏样本:

[
  {
    _id: "bmasndvhjbcw",
    name: "lucas",
    occupation: "scientist",
    age: 55,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00
  },
  {
    _id: "bmasndvhjbcx",
    name: "mark",
    occupation: "scientist",
    age: 45,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00
  },
  {
    _id: "bmasndvhjbca",
    name: "stuart",
    occupation: "lab assistant",
    age: 25,
    location: "texas",
    joining_date: 2019-01-02T20:25:16.068+00:00
  },
  {
    _id: "bmasndvhjbcq",
    name: "cooper",
    occupation: "physicist",
    age: 69,
    location: "texas"
  }
]

哪个文档有 joining_date 列需要通过检查日期来添加一个值增加的字段,例如joining_date_count:1

如果日期相同,例如 marklucas 两种情况。 count 应将其视为不同的值并增加计数。

预期输出:

[
  {
    _id: "bmasndvhjbcw",
    name: "lucas",
    occupation: "scientist",
    age: 55,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00,
    joining_date_count:1
  },
  {
    _id: "bmasndvhjbcx",
    name: "mark",
    occupation: "scientist",
    age: 45,
    location: "texas",
    joining_date: 2019-01-01T15:24:15.068+00:00,
    joining_date_count:2
  },
  {
    _id: "bmasndvhjbca",
    name: "stuart",
    occupation: "lab assistant",
    age: 25,
    location: "texas",
    joining_date: 2019-01-02T20:25:16.068+00:00,
    joining_date_count:3
  },
  {
    _id: "bmasndvhjbcq",
    name: "cooper",
    occupation: "physicist",
    age: 69,
    location: "texas"
  }
]

【问题讨论】:

  • 您的收藏有多大?因为如果文档不是基于joining_date从高(最新)到低(旧)保存的,那么我们需要实现$sort,这在大型数据集上可能会出现问题..
  • 集合很小,我们可以对其使用排序。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

这个聚合添加了一个带计数器的字段:

db.collection.aggregate( [
  { 
      $match: { 
          joining_date: { $exists: true } 
      } 
  },
  { 
      $group: { 
          _id: null, 
          docs: { $push: "$$ROOT" } 
      } 
  },
  { 
      $project: { 
          _id: 0,
         R: { 
             $map: {
                 input: { $range: [ 0, { $size: "$docs" } ] },
                 in: {
                     $mergeObjects: [ 
                         { joining_date_count: { $add: [ "$$this", 1 ] } },
                         { $arrayElemAt: [ "$docs", "$$this" ] }
                     ]
                 }
             }
         }
      }
  },
  { 
      $unwind: "$R" 
  },
  { 
      $replaceRoot: { newRoot: "$R" } 
  }
] )

【讨论】:

【解决方案2】:

您可以尝试以下查询:

db.collection.aggregate([
    /** Sort on joining_date field which will arrange docs with missing field at top & ascending where field exists */
    {
      $sort: {
        joining_date: 1
      }
    },
    /** group on empty & push every doc in collection to an array field named data */
    {
      $group: {
        _id: "",
        data: {
          $push: "$$ROOT"
        }
      }
    },
    /** split data array into two array one has doc which doesn't field & other has docs which does have field */
    {
      $addFields: {
        data: {
          $reduce: {
            input: "$data",
            initialValue: {
              missingField: [],
              fieldExists: []
            },
            in: {
              missingField: {
                $cond: [
                  {
                    "$ifNull": [
                      "$$this.joining_date",
                      false
                    ]
                  },
                  "$$value.missingField",
                  {
                    $concatArrays: [
                      "$$value.missingField",
                      [
                        "$$this"
                      ]
                    ]
                  }
                ]
              },
              fieldExists: {
                $cond: [
                  {
                    "$ifNull": [
                      "$$this.joining_date",
                      false
                    ]
                  },
                  {
                    $concatArrays: [
                      "$$value.fieldExists",
                      [
                        "$$this"
                      ]
                    ]
                  },
                  "$$value.fieldExists"
                ]
              }
            }
          }
        }
      }
    },
    /** Add new field 'joining_date_count' to docs based on that doc index in fieldExists array &
     *  finally concatinate missingField with newly formed fieldExists array */
    {
      $addFields: {
        "data": {
          $concatArrays: [
            "$data.missingField",
            {
              $map: {
                input: "$data.fieldExists",
                in: {
                  $mergeObjects: [
                    "$$this",
                    {
                      joining_date_count: {
                        $add: [
                          1,
                          {
                            $indexOfArray: [
                              "$data.fieldExists",
                              "$$this"
                            ]
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            }
          ]
        }
      }
    },
    /** unwind data array */
    {
      $unwind: "$data"
    },
    /** replace each docs root as data field */
    {
      $replaceRoot: {
        newRoot: "$data"
      }
    }
  ])

测试: MongoDB-Playground

【讨论】:

  • 天啊!另一个让 SQL 蒙羞的 mongodb 聚合示例 ? 干得好 ?
猜你喜欢
  • 2023-01-11
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
  • 2021-11-27
  • 2021-06-26
  • 2021-08-08
  • 2022-11-23
相关资源
最近更新 更多