Re: Aggregation framework questions

81 views
Skip to first unread message

Thomas Rueckstiess

unread,
Sep 9, 2012, 10:25:26 PM9/9/12
to mongod...@googlegroups.com
Hi,

Reg. Question 1:
You can $match the documents that have metric2 set and find the minimum over these, for example:

db.metric.aggregate({$match: {'metrics.metric2': {$exists: true}}}, 
                    {$group: {'_id': {'year':'$year'}, 'min_metric2': {'$min': '$metrics.metric2'}}})
{
"result" : [
{
"_id" : {
"year" : 2012
},
"min_metric2" : 20
}
],
"ok" : 1
}

Question 2: While simply setting a string in a $project field yields and error, you can use a work-around with $substr (or similarly $toLower, $toUpper):

db.metric.aggregate({$project: {_id: '$_id', myString:{$substr:['myValue', 0, -1]}}})
{
"result" : [
{
"_id" : ObjectId("504d440e105de2ae6baaae9b"),
"myString" : "myValue"
},
{
"_id" : ObjectId("504d440e105de2ae6baaae9c"),
"myString" : "myValue"
},
{
"_id" : ObjectId("504d440e105de2ae6baaae9d"),
"myString" : "myValue"
},
{
"_id" : ObjectId("504d440e105de2ae6baaae9e"),
"myString" : "myValue"
},
{
"_id" : ObjectId("504d440f105de2ae6baaae9f"),
"myString" : "myValue"
}
],
"ok" : 1
}


For Question 3: 
could you specify what exactly you want to achieve? There is a $cond operator that you could use to change the value of a certain field. For example, if you want to set the value to true if metric1 is < 30, you could do:

db.metric.aggregate({$project: {_id:'$_id', condValue: {$cond:[{$lt: ['$metrics.metric1', 30]}, true, false ]}}})
{
"result" : [
{
"_id" : ObjectId("504d440e105de2ae6baaae9b"),
"condValue" : false
},
{
"_id" : ObjectId("504d440e105de2ae6baaae9c"),
"condValue" : false
},
{
"_id" : ObjectId("504d440e105de2ae6baaae9d"),
"condValue" : true
},
{
"_id" : ObjectId("504d440e105de2ae6baaae9e"),
"condValue" : true
},
{
"_id" : ObjectId("504d440f105de2ae6baaae9f"),
"condValue" : false
}
],
"ok" : 1
}


Hope this answers your questions.

Regards,
Thomas



On Monday, September 10, 2012 4:11:52 AM UTC+10, Sujee wrote:
Hello everyone,

I have few questions about new aggregation framework.

Question 1. Does non-existence of a field considered as $min value in a $group?

For e.g. In the following script, min_metric2 is not printed because at-least one document doesn't have it. How do I find the min value among the remaining documents?

db.metric.remove({});
db.metric.save({year: 2012, month: 1, metrics: {metric1: 30, metric2: 80}});
db.metric.save({year: 2012, month: 2, metrics: {metric1: 50, metric2: 20}});
db.metric.save({year: 2012, month: 3, metrics: {metric1: 10}});
db.metric.save({year: 2012, month: 4, metrics: {metric1: 20, metric2: 40}});
db.metric.save({year: 2012, month: 5, metrics: {metric1: 40, metric2: 60}});

var result = db.metric.aggregate
(
[
{
$group: {
_id: {year: "$year"}, 
min_metric1: {$min: "$metrics.metric1"},
min_metric2: {$min: "$metrics.metric2"},
max_metric1: {$max: "$metrics.metric1"},
max_metric2: {$max: "$metrics.metric2"},
}
}
]
);

printjson(result);

================================================

{
        "result" : [
                {
                        "_id" : {
                                "year" : 2012
                        },
                        "min_metric1" : 10,
                        "max_metric1" : 50,
                        "max_metric2" : 80
                }
        ],
        "ok" : 1
}

Question 2: How do I set a fixed String (hard-coded value) to a field in $project or anywhere else in the pipeline?

Question 3: Is it possible to define a field conditionally (based on a computed value) in $project?

Thank you.

Reply all
Reply to author
Forward
0 new messages