无法计算平均时间

时间:2014-03-22 23:40:41

标签: mongodb mongodb-query aggregation-framework

3天到MongoDB,我发现它不是很流畅。我只是想计算一个字段的平均时间,但我一直遇到各种各样的问题。

这是我的代码:

db.results.group({
     key:{"profile.Zend_Http_Client_Adapter_Socket::read==>fgets":{$exists:true}},
     initial: {count: 0, total:0},
     reduce: function(doc, out){ 
         out.count++; 
         out.total += doc."profile.Zend_Http_Client_Adapter_Socket::read==>fgets.wt";
     },
     finalize: function(out){
            out.avg = out.total/out.count;
     }
});

错误:

SyntaxError:意外字符串

以上是一个非常幼稚的错误,但我无法理解为什么它会说明这一点,我能想到的唯一可信的原因是我在这里指定的键是引号,因此Mongo感到困惑。

但是,这些键在我的集合中都是引号,所以我没有理由不断出现这种语法错误吗?

示例文件:

{
    "_id" : ObjectId("532a2a986803faba658b456b"),
    "profile" : {
        "main()==>register_shutdown_function" : {
            "ct" : 1,
            "wt" : 13,
            "cpu" : 0,
            "mu" : 1568,
            "pmu" : 1000
        },
        "main()==>load::htdocs/index.php" : {
            "ct" : 1,
            "wt" : 17,
            "cpu" : 0,
            "mu" : 1736,
            "pmu" : 4296
},
        {"Zend_Http_Client_Adapter_Curl::write==>curl_exec" : {                                           
            "ct" : 3,
            "wt" : 54782314,
            "cpu" : 16001,
            "mu" : 83288,
            "pmu" : 49648
        }, ....

2 个答案:

答案 0 :(得分:2)

根据评论,您的问题是形成有效的JavaScript。你的“关键”价值似乎也不是你真正想要的。但是,你应该赞成aggregate函数而不是使用“group”

db.results.aggregate([
    { "$match": {
        "$and": [
            { "profile.Zend_Http_Client_Adapter_Socket::read==>fgets.wt": {
                "$exists": true 
            }},
            { "profile.Zend_Http_Client_Adapter_Socket::read==>fgets.wt": { 
               "$not": { "$type": 2 }
            }}
        ]
    }},
    { "$group": {
        "_id": null,
        "total": { "$sum": 
            "$profile.Zend_Http_Client_Adapter_Socket::read==>fgets.wt"
        },
        "count": { "$sum": 1 }
    }},

    { "$project": {
        "_id": 0,
        "avg": { "$divide": [ "$total", "$count" ] }
   }}
])

聚合管道排序取代了之前引入的groupdistinct等函数。对于除了琐碎的操作之外的所有操作成为您最喜欢的选择。

它将以更快的速度运行,并且在本机代码中处理,而不是JavaScript引擎。

另请参阅文档中的SQL to aggregation mapping chart

数据问题

您的样本不是很完整。要解决我必须在这样的文档中提出的所有问题:

{
    "profile": {
        "Zend_Http_Client_Adapter_Socket::read==>fgets": {                                           
            "ct" : 3,
            "wt" : 54782314,
            "cpu" : 16001,
            "mu" : 83288,
            "pmu" : 49648
        },
    }
}

此外,您的文档示例中包含一些无效字段:

{
    "_id" : ObjectId("532a2a986803faba658b456b"),
    "profile" : {
        "main()==>register_shutdown_function" : {
            "ct" : 1,
            "wt" : 13,
            "cpu" : 0,
            "mu" : 1568,
            "pmu" : 1000
        },
        "main()==>load::htdocs/index.php" : { <-- Invalid
            "ct" : 1,
            "wt" : 17,
            "cpu" : 0,
            "mu" : 1736,
            "pmu" : 4296
},

因此该字段不能存在,因为字段名称中包含.,不允许出现明显的子文档原因。

答案 1 :(得分:0)

@Neils的回答让我找到了正确的解决方案:

db.results.aggregate([
    {
       $match: {
            "profile.Zend_Http_Client_Adapter_Socket::read==>fgets.wt": {
                "$exists": true
            }
        }
    },
    {
        $group: {
            "_id": null,
            "total": {
                $sum: "$profile.Zend_Http_Client_Adapter_Socket::read==>fgets.wt"
            },
            "count": {
                $sum: 1
            }
        }
    },
    {
        $project: {
            "_id": 0,
            "count": "$count",
            "avg": {
                $divide: [
                    "$total",
                    "$count"
                ]
            }
        }
    }
]);