Use the aggregation framework:
db.collection.aggregate([
{ "$project": {
"answer": { "$cond": [
{ "$gt": [ "$a.last_login", "$b.last_login" ] },
{ "$cond": [
{ "$gt": [ "$a.last_login", "$c.last_login" ] },
{
"key": { "$literal": "a" },
"last_login": "$a.last_login"
},
{
"key": { "$literal": "c" },
"last_login": "$c.last_login"
}
]},
{ "$cond": [
{ "$gt": [ "$b.last_login", "$c.last_login" ] },
{
"key": { "$literal": "b" },
"last_login": "$b.last_login"
},
{
"key": { "$literal": "c" },
"last_login": "$c.last_login"
},
]}
]}
}}
])
It works, but it's actually quite mental. So the lesson to learn here it "do not use sub-documents in this way", and use arrays instead:
{
"apps": [
{ "type": "a", "last_login": ISODate("2013-08-07T10:18:39.371Z") },
{ "type": "b", "last_login": ISODate("2013-08-21T09:53:10.769Z") },
{ "type": "c", "last_login": ISODate("2013-08-30T09:53:10.769Z") }
]
}
That makes things much more simple:
db.collection.aggregate(
{ "$unwind": "$apps" },
{ "$sort": { "apps.last_login": -1 } },
{ "$group": {
"_id": "$_id",
"answer": { "$first": "$apps" }
}}
])
Much easier isn't it.
NOTE: The $literal
operator was introduced in MongoDB 2.6. You might possibly find some references on the net to $const
as an alternate operator, but this is not actually officially supported as that operator actually exists for another purpose.
You can do exactly the same thing in earlier server versions of MongoDB using the $cond
operator instead:
"key": { "$cond": [ 1, "a", 0 ] }
This works as the result arguments to $cond
are actually delivered as "literal" values, or "whatever you type in there", so no variable substitutions.