簡體   English   中英

MongoDB 聚合 - 如何按速率獲取百分比值

[英]MongoDB aggregation - how to get a percentage value by rate

我正在嘗試獲取有關基於行的所有數據收集的信息

我的數據:

{
    _id : 1,
    age : 21,
    salary : 2500
},
{
    _id : 2,
    age : 42,
    salary : 4300
},
{
    _id : 3,
    age : 32,
    salary : 3100
},
{
    _id : 4,
    age : 18,
    salary : 7000
},
{
    _id : 5,
    age : 25,
    salary : 5600
},
{
    _id : 6,
    age : 28,
    salary : 5200
}
,
{
    _id : 7,
    age : 38,
    salary : 5000
},
{
    _id : 8,
    age : 28,
    salary : 5200
}

我想將值分成四個選項。

第一個選項是 25%。

第二個選項值在 25% 到 50% 之間。

50% 到 75% 之間的第三個選項和

最后一個選項介於 75% 和 100% 之間。

所以當我想拉出一個對象時,它會顯示相對於其他值的值。

例如 :

{
    _id : 4,
    age : 'less than 25 percent',
    salary : 'more than 75 percent'
}

看看這是否符合您的要求。

解釋

Mongodb 聚合提供了更多的分析操作來計算數據。 通過$facet操作,我們可以將多個聚合合二為一。

我們計算salaryage最小值/最大值。 然后我們用這個公式計算每個salaryage百分比

 x  − min
---------- x 100
max − min

使用$switch我們定義了 4 個選項:小於 25、小於 50、小於 75 和更多 han 75


db.collection.aggregate([
  {
    $facet: {
      extremes: [
        {
          $group: {
            _id: null,
            maxAge: {
              $max: "$age"
            },
            minAge: {
              $min: "$age"
            },
            maxSalary: {
              $max: "$salary"
            },
            minSalary: {
              $min: "$salary"
            }
          }
        }
      ],
      root: [
        {
          $match: {}
        }
      ]
    }
  },
  {
    $set: {
      extremes: {
        $arrayElemAt: [
          "$extremes",
          0
        ]
      }
    }
  },
  {
    $unwind: "$root"
  },
  {
    $addFields: {
      root: {
        agePercent: {
          $toInt: {
            $multiply: [
              {
                $divide: [
                  {
                    $subtract: [
                      "$root.age",
                      "$extremes.minAge"
                    ]
                  },
                  {
                    $subtract: [
                      "$extremes.maxAge",
                      "$extremes.minAge"
                    ]
                  }
                ]
              },
              100
            ]
          }
        },
        salaryPercent: {
          $toInt: {
            $multiply: [
              {
                $divide: [
                  {
                    $subtract: [
                      "$root.salary",
                      "$extremes.minSalary"
                    ]
                  },
                  {
                    $subtract: [
                      "$extremes.maxSalary",
                      "$extremes.minSalary"
                    ]
                  }
                ]
              },
              100
            ]
          }
        }
      }
    }
  },
  {
    $replaceWith: "$root"
  },
  {
    $project: {
      age: {
        $switch: {
          branches: [
            {
              case: {$lt: ["$agePercent",25]},
              then: "less than 25 percent"
            },
            {
              case: {$lt: ["$agePercent",50]},
              then: "less than 50 percent"
            },
            {
              case: {$lt: ["$agePercent",75]},
              then: "less than 75 percent"
            },
            {
              case: {$gte: ["$agePercent",75]},
              then: "more than 75 percent"
            }
          ],
          default: "Unknown"
        }
      },
      salary: {
        $switch: {
          branches: [
            {
              case: {$lt: ["$salaryPercent",25]},
              then: "less than 25 percent"
            },
            {
              case: {$lt: ["$salaryPercent",50]},
              then: "less than 50 percent"
            },
            {
              case: {$lt: ["$salaryPercent",75]},
              then: "less than 75 percent"
            },
            {
              case: {$gte: ["$salaryPercent",75]},
              then: "more than 75 percent"
            }
          ],
          default: "Unknown"
        }
      }
    }
  }
])

蒙戈游樂場

您可以使用$bucketAuto來做到這一點,默認情況下,它會將集合的所有文檔拆分為最有可能均等指定的 no.of 存儲桶,

腳步 :

  1. 使用$facet創建數組的一個age & 一個salary ,每個數組 4 個子文檔,所有文檔均等地拼接到 4 個存儲桶(子文檔)中。 將每個映射文檔添加到data數組中。
  2. 展開agesalary以獲取對象及其特定索引。
  3. 使用$addFields將現有字段agesalary替換為與其在存儲桶中的位置相對應的文本。
  4. 使用$project & $concatArrays將兩個數組合並為名為data單個數組。
  5. _id上展開data數組和$group將唯一文本添加到agesalary
  6. agesalary是單個元素(字符串)的數組,因此通過使用$arrayElemAt獲取第一個元素將agesalary作為字符串類型的字段。

詢問 :

db.collection.aggregate([
    {
        $facet: {
            "age": [
                {
                    $bucketAuto: {
                        groupBy: "$age",
                        buckets: 4,
                        output: {
                            "data": { $push: { '_id': "$$ROOT._id", age: "$$ROOT.age" } }
                        }
                    }
                }
            ],
            "salary": [
                {
                    $bucketAuto: {
                        groupBy: "$salary",
                        buckets: 4,
                        output: {
                            "data": { $push: { '_id': "$$ROOT._id", salary: "$$ROOT.salary" } }
                        }
                    }
                }
            ]
        }
    }, { $unwind: { path: '$age', includeArrayIndex: "arrayIndexAge" } },
       { $unwind: { path: '$salary', includeArrayIndex: "arrayIndexSalary" } },
    {
        $addFields: {
            'age.data.age': {
                $switch: {
                    branches: [
                        { case: { $eq: ['$arrayIndexAge', 0] }, then: "less than 25 percent" },
                        { case: { $eq: ['$arrayIndexAge', 1] }, then: "​​between 25 and 50 percent" },
                        { case: { $eq: ['$arrayIndexAge', 2] }, then: "between 50 and 75 percent" },
                        { case: { $eq: ['$arrayIndexAge', 3] }, then: "more than 75 percent" }
                    ]
                }
            },
            'salary.data.salary': {
                $switch: {
                    branches: [
                        { case: { $eq: ['$arrayIndexSalary', 0] }, then: "less than 25 percent" },
                        { case: { $eq: ['$arrayIndexSalary', 1] }, then: "​​between 25 and 50 percent" },
                        { case: { $eq: ['$arrayIndexSalary', 2] }, then: "between 50 and 75 percent" },
                        { case: { $eq: ['$arrayIndexSalary', 3] }, then: "more than 75 percent" }
                    ]
                }
            }
        }
    }, { $project: { data: { $concatArrays: ['$age.data', '$salary.data'] } } }, { $unwind: '$data' },
    { $group: { _id: '$data._id', age: { $addToSet: '$data.age' }, salary: { $addToSet: '$data.salary' } } },
    { $addFields: { age: { $arrayElemAt: ['$age', 0] }, salary: { $arrayElemAt: ['$salary', 0] } } }])

測試: MongoDB-Playground

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM