在将结果发送回MongoDB之前进行数据处理

时间:2019-02-15 14:51:33

标签: mongodb aggregation-framework

我们需要根据一些定义的算法对记录进行排名。我们的MongoDB中有4个字段,如下所示:

{
"rating" : 3.5
"review" : 4
"revenue" : 100
"used" : 3.9
},
{
"rating" : 1.5
"review" : 2
"revenue" : 10
"used" : 2.1
}

查询数据时,我们将发送%作为权重进行计算。因此,假设我们发送30%的评级,30%的评论以及20%的收入和使用率。

现在,我们需要根据以下计算对每条记录进行评分。

Score per column = (Existing Value - Average(Column) / StandardDeviation) * %weightage

for rating = (3.5 - 2.5) /1 * 30% = .03

因此,我们需要计算每列(或每个字段)的得分,然后所有4个字段的总和将为每条记录得分。

是否可以使用任何MongoDB内置函数进行这种计算?

预先感谢

2 个答案:

答案 0 :(得分:0)

Mongo具有默认的运算符,用于查找标准偏差($ stdDevPop)和查找平均值($ avg),并且显然也用于减法,乘法和除法。

因此,使用所有这些运算符,您绝对可以为您所需的内容编写汇总。

我已经在下面完成了评分,您可以对其他字段使用相同的逻辑。

此外,用您的%weightage代替0.3。

db.collection.aggregate([
{
    $match: {
      rating: {
        $ne: null
      }
    }
  },
  {
    $group: {
      _id: null,
      ratings: {
        $push: "$rating"
      },
      avg_rating: {
        $avg: "$rating"
      },
      std_deviation_rating: {
        $stdDevPop: "$rating"
      }
    }
  },
  {
    $project: {
      ratings: {
        $map: {
          input: "$ratings",
          as: "rating",
          in: {
            $multiply: [
              {
                $divide: [
                  {
                    $subtract: [
                      "$$rating",
                      "$avg_rating"
                    ]
                  },
                  "$std_deviation_rating"
                ]
              },
              0.3
            ]
          }
        }
      }
    }
  }
])

答案 1 :(得分:0)

两个查询可能是第一个查询获取avg / std值的方法,然后是第二个查询以迭代光标并计算排名。

您喜欢在聚合管道中进行操作,可以在3.6版本中使用$facet

基本上,您正在构面阶段内运行多个聚合管道查询,然后计算排名。

db.collection.aggregate([
{
  "$facet":{
    "avgstddev":[
      {"$group":{
        "_id":null,
        "avgRating":{"$avg":"$rating"},
        "stdDevRating":{"$stdDevPop":"$rating"},
         ... other fields
      }}
   ],
   "docs":[
     {"$match":{}}
    ]
  }
},
{"$project":{
  "rank":{
    "$let":{
      "vars":{"avgstddevdoc":{"$arrayElemAt":["$avgstddev",0]}},
      "in":{
        "$map":{
          "input":"$docs",
          "in":{
            "$add":[
              {"$multiply":[
                {"$subtract":[
                  "$$this.rating",
                  {"$divide":["$$avgstddevdoc.avgRating","$$avgstddevdoc.stdDevRating"]}
                ]},
                0.3
              ]},
              other calculations
            ]
          }
        }
      }
    }
  }
}}
])