【问题标题】:How Do I calculate percentage on array field using mongodb aggregation?如何使用 mongodb 聚合计算数组字段的百分比?
【发布时间】:2020-03-19 04:56:34
【问题描述】:

我有以下文件

users = [
  {
    type: 'A',
    name: 'anil',
    logins: [
      { at: '2-3-2019', device: 'mobile' },
      { at: '3-3-2019', device: 'desktop' },
      { at: '4-3-2019', device: 'tab' },
      { at: '5-3-2019', device: 'mobile' }
    ]
  },
  {
    type: 'A',
    name: 'rakesh',
    logins: [
      { at: '2-3-2019', device: 'desktop' },
      { at: '3-3-2019', device: 'mobile' },
      { at: '4-3-2019', device: 'desktop' },
      { at: '5-3-2019', device: 'tab' }
    ]
  },
  {
    type: 'A',
    name: 'rahul',
    logins: [
      { at: '2-3-2019' device: 'tab' },
      { at: '3-3-2019' device: 'mobile' },
      { at: '4-3-2019' device: 'tab' },
      { at: '5-3-2019' device: 'tab' }
    ]
  }
]

我需要计算每个用户使用“A”类型设备的百分比。

如果我们查看用户 anil 设备使用情况,

mobile: 50%
desktop: 25%
tab: 25%

使用率最高的是移动设备,使用率50%,因此应将其视为移动设备。 就像上面的最终输出一样,

[
  {
    name: 'anil',
    device: 'mobile',
    logins: 50%
  },
  {
    name: 'rakesh',
    device: 'desktop',
    logins: 50%
  },
  {
    name: 'rahul',
    device: 'tab',
    logins: 75%
  }
]

感谢您的帮助。

【问题讨论】:

  • 这可以使用 javascript .reduce 方法来实现,但是由于您希望 mongo 进行处理,请查看 mongo docs 中的 https://docs.mongodb.com/manual/aggregation/#map-reduce 方法

标签: node.js mongodb mongodb-query aggregation-framework


【解决方案1】:

你可以使用下面的聚合

这里的整体逻辑是在数组中找到重复项,之后你只需要在logins数组上做$map,使用公式计算设备的百分比

(numberOfDevices * 100) / total size of the array

如果你从下面的聚合中一一去掉就更好了。

db.collection.aggregate([
  { "$match": { "type": "A" }},
  { "$addFields": {
    "logins": {
      "$arrayToObject": {
        "$map": {
          "input": { "$setUnion": ["$logins.device"] },
          "as": "m",
          "in": {
            "k": "$$m",
            "v": {
              "$divide": [
                {
                  "$multiply": [
                    { "$size": {
                      "$filter": {
                        "input": "$logins",
                        "as": "d",
                        "cond": {
                          "$eq": ["$$d.device", "$$m"]
                        }
                      }
                    }},
                    100
                  ]
                },
                { "$size": "$logins" }
              ]
            }
          }
        }
      }
    }
  }}
])

MongoPlayground

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "logins": {
      "desktop": 25,
      "mobile": 50,
      "tab": 25
    },
    "name": "anil",
    "type": "A"
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "logins": {
      "desktop": 50,
      "mobile": 25,
      "tab": 25
    },
    "name": "rakesh",
    "type": "A"
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "logins": {
      "mobile": 25,
      "tab": 75
    },
    "name": "rahul",
    "type": "A"
  }
]

精确输出->这里我只是在得到所有设备的百分比后从对象数组中找到$max元素。

db.collection.aggregate([
  { "$match": { "type": "A" }},
  { "$addFields": {
    "logins": {
      "$map": {
        "input": { "$setUnion": ["$logins.device"] },
        "as": "m",
        "in": {
          "k": "$$m",
          "v": {
            "$divide": [
              {
                "$multiply": [
                  { "$size": {
                    "$filter": {
                      "input": "$logins",
                      "as": "d",
                      "cond": {
                        "$eq": ["$$d.device", "$$m"]
                      }
                    }
                  }},
                  100
                ]
              },
              { "$size": "$logins" }
            ]
          }
        }
      }
    }
  }},
  { "$replaceRoot": {
    "newRoot": {
      "$mergeObjects": [
        "$$ROOT",
        {
          "$arrayElemAt": [
            "$logins",
            {
              "$indexOfArray": [
                "$logins.v",
                { "$max": "$logins.v" }
              ]
            }
          ]
        }
      ]
    }
  }},
  { "$project": { "logins": 0 }}
])

MongoPlayground

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "k": "mobile",
    "name": "anil",
    "type": "A",
    "v": 50
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "k": "desktop",
    "name": "rakesh",
    "type": "A",
    "v": 50
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "k": "tab",
    "name": "rahul",
    "type": "A",
    "v": 75
  }
]

【讨论】:

  • 感谢@Ashh,这与预期的输出完全相同。
猜你喜欢
  • 2023-01-03
  • 1970-01-01
  • 2014-12-24
  • 2014-02-27
  • 1970-01-01
  • 2012-01-20
  • 2017-01-03
  • 2019-01-08
  • 2019-04-06
相关资源
最近更新 更多