特殊的mongo统计,该怎么写?

mongo数据项形似如下:

{'key1':1,'key2':{'a':'1','b':2,'c':3,'d':''}}
{'key1':3,'key2':{'d':'','ty':2,'gh':3,'sd':''}}
{'key1':5,'key2':{'k':'1','b':2,'d':''}}
{'key1':2,'key2':{'q':1,'bf':2,'cw':3,'d':''}}
{'key1':1,'key2':{'su':'','b':2,'c':3,'d':''}}
{'key1':5,'key2':{'ba':1,'d':''}}
{'key1':1,'key2':{'er':'','b':2,'g':'','d':''}}

每条数据的key2中的key都各不相同,有多有少,value也有的为空。
我想统计 针对每一种key1,其key2的value完整度平均比例

很拗口是不是?我解释一下。

也就是首先按key1分组,我们看到key一共有 1,2,3,5 四种,所以分为四组。

其中1这一组,有3条,分别是:

{'key1':1,'key2':{'a':1,'b':2,'c':3,'d':''}}
{'key1':1,'key2':{'su':'','b':2,'c':3,'d':''}}
{'key1':1,'key2':{'er':'','b':2,'g':'','d':''}}

这三条中,第一条的key2,a,b,c都不是空字符串'',d是,那么第一条的完整度为 3/4 = 75%
以此计算,第二条与第三条的完整度分别是 50% 和 25%
最后计算 这三条的平均完整度是 (75%+50%+25%)/3 = 50%

对每一组都进行如上统计,最后得出这样的结果:

{'_id':1,'num':50%}
{'_id':2,'num':75%}
{'_id':3,'num':50%}
{'_id':5,'num':58%}

这样的统计在mongo里该怎么写呢?在pymongo里能写出对应的吗?

阅读 2.9k
2 个回答

回来赴约了。这个查询可以这样写。大概就是用map/reduce的思路来处理。剩下的就是如何使用$map, $reduce, $let, $objectToArray这些东西的问题。先看看能不能理解一下,有不明白的地方再讨论。

db.test.aggregate([{
    $project: {
        key1: 1,
        percentage: {
            $let: {
                vars: {
                    key2: {
                        $reduce: {
                            input: {
                                $map: {
                                    input: {
                                        $objectToArray: "$key2"
                                    },
                                    as: "keys",
                                    in: {
                                        $cond: [{
                                            $eq: ["$$keys.v", ""]
                                        }, 0, 1]
                                    }
                                }
                            },
                            initialValue: {
                                complete: 0,
                                total: 0
                            },
                            in: {
                                complete: {
                                    $add: ["$$value.complete", "$$this"]
                                },
                                total: {
                                    $add: ["$$value.total", 1]
                                }
                            }
                        }
                    }
                },
                in: {
                    $divide: ["$$key2.complete", "$$key2.total"]
                }
            }
        }
    }
}, {
    $group: {
        _id: "$key1",
        percentage: {
            $avg: "$percentage"
        }
    }
}])

以你的数据跑出的结果是:

{ "_id" : 2, "percentage" : 0.75 }
{ "_id" : 5, "percentage" : 0.5833333333333333 }
{ "_id" : 3, "percentage" : 0.5 }
{ "_id" : 1, "percentage" : 0.5 }
新手上路,请多包涵

mongodb有一个操作符$group

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题