Reputation: 5085
3 days old into MongoDB, and I am not finding it very fluid. I am simply trying to compute the average time for a field but I keep running into all sorts of problems.
Here is my code:
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;
}
});
The error:
SyntaxError: Unexpected String
The above is a very childish error, but I can't understand why it would state this, the only plausible reason I can think of is that the keys I have specified here are in quotes hence Mongo is getting confused.
BUT, these keys ARE in quotes in my collection, so there should be no reason why I keep getting this syntax error right ?
Sample document:
{
"_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
}, ....
Upvotes: 0
Views: 453
Reputation: 151072
As per the comment your problem is one of forming valid JavaScript. Also your "key" value would not seem to be what you really want. There is however the aggregate function that you should be favoring over the use of "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" ] }
}}
])
The aggregation pipeline sort of supercedes earlier introduced functions such as group
and distinct
. And for all but trivial operations should be your favored choice.
It will run much faster as well as this is processed in native code and not the JavaScript engine.
Also see the SQL to aggregation mapping chart in the documentation.
Your sample is not very complete. To sort out all issues I have to put in a document like this:
{
"profile": {
"Zend_Http_Client_Adapter_Socket::read==>fgets": {
"ct" : 3,
"wt" : 54782314,
"cpu" : 16001,
"mu" : 83288,
"pmu" : 49648
},
}
}
Also your document example has some invalid fields in it:
{
"_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
},
So that field cannot exist as it has a .
in the field name, which for obvious sub-document reasons is not allowed.
Upvotes: 2
Reputation: 5085
@Neils answer led me to the correct solution:
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"
]
}
}
}
]);
Upvotes: 0