how to get the max of my collection without the _id

40 views
Skip to first unread message

MANU

unread,
May 25, 2012, 8:49:01 AM5/25/12
to mongodb-user
Hi everybody,

I developped a map/reduce with the aggregation framework of mongo.

Here is my data :

db.coll.save({a:'Martin',b:'wesh',c:5})
db.coll.save({a:'Martin',b:'wesh',c:15})
db.coll.save({a:'Martin',b:'wesh',c:2})
db.coll.save({a:'Manu',b:'bri',c:1})
db.coll.save({a:'Manu',b:'bri',c:2})
db.coll.save({a:'Manu',b:'bri',c:10})
db.coll.save({a:'Manu',b:'bri',c:6})

The result I want :

martin wesh : 2
Manu bri : 1

Here is my code :

db.coll.group(
{key: { a:true, b:true },
reduce: function(obj,prev) { if (prev.min > obj.c)
{prev.min = obj.c}; },
initial: { min: 15 }
});

I want to replace : " initial: { min: 15 } " BY " initial: { min:
db.coll.find({},{c:1}).sort({c:-1}).limit(1) } "

but the last way return {"_id" : 5654653 , "c" : 15} and not only 15

What's the solution guys ?

Thanks a lot.

Best regards





Sam Millman

unread,
May 25, 2012, 10:16:29 AM5/25/12
to mongod...@googlegroups.com
I don't it's possible and nor would it be reliable since the sorting would be undone in the grouping itself.

Best thing is to use a sorting algorithm on the returned BSON object to sort your group results by your desired field.






--
You received this message because you are subscribed to the Google
Groups "mongodb-user" group.
To post to this group, send email to mongod...@googlegroups.com
To unsubscribe from this group, send email to
mongodb-user...@googlegroups.com
See also the IRC channel -- freenode.net#mongodb

Dan Crosta

unread,
May 25, 2012, 10:33:52 AM5/25/12
to mongod...@googlegroups.com
It looks like you're actually computing the minimum "c" value for each person, not the maximum -- was that just a typo in your subject line?

As for the particular question, you can use javascript's "typeof" operator to ensure that the first value for any given person is taken as the minimum, and then that any subsequent value is taken if it is smaller than the current value. By the time the group() call finishes, this will give you the minimum for each person:

db.coll.group({
    key: {a: true, b: true},
    reduce: function (obj, prev) {
        if (obj.c < prev.min || typeof(prev.min) == "undefined") {
            prev.min = obj.c;
        }
    },
    initial: {}
})

Hope this helps,
- Dan

Sam Millman

unread,
May 25, 2012, 10:40:18 AM5/25/12
to mongod...@googlegroups.com
Wait I think you may have been asking somehting else now that I look at:


"but the last way return {"_id" : 5654653 , "c" : 15} and not only 15"

Do you mean it return _id in the group() function from doing that? It appears I completely misread.

You might be able to solve this with adding _id:0 but it will still output {c:15} as such you may want to use Dan's approach.

--

MANU

unread,
May 25, 2012, 10:57:15 AM5/25/12
to mongod...@googlegroups.com
the Dan's solution is perfect.

Thank you guys.

A last things about my probleme :
isn't it possible to do something like that ? :

var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1) ;

print a[1]

In order to print the value 15 only ???

Sam Millman

unread,
May 25, 2012, 11:00:57 AM5/25/12
to mongod...@googlegroups.com
No but you can do: a[1][c]

MANU

unread,
May 25, 2012, 11:10:55 AM5/25/12
to mongod...@googlegroups.com
I've got this result :


> var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1)
> a
{ "_id" : ObjectId("4fbf9bf2ab98db2e62486a3a"), "c" : 15 }


> var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1)
> a[1][c]
Fri May 25 17:08:22 ReferenceError: c is not defined (shell):1


> var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1)
> a[1]["c"]
Fri May 25 17:08:58 TypeError: a[1] has no properties (shell):1

I'd like to do :

>a/3
5

Sam Millman

unread,
May 25, 2012, 11:15:29 AM5/25/12
to mongod...@googlegroups.com
Ooooh, I see now. Yea the problem is that it's returning an array (or cursor, depending on where your doing that).

Hmmmm, a[0]["c"] is prolly the best way, if your dong it from console?

Sam Millman

unread,
May 25, 2012, 11:16:30 AM5/25/12
to mongod...@googlegroups.com
Sorry it seems a["c"] will do it according to your output since the console does that for you

MANU

unread,
May 25, 2012, 11:22:46 AM5/25/12
to mongod...@googlegroups.com
Fine !
thanks a lot
Fri May 25 17:08:58 TypeError: a[1] has no properties (shell):1


Le vendredi 25 mai 2012 17:15:29 UTC+2, Sammaye a écrit :
Ooooh, I see now. Yea the problem is that it's returning an array (or cursor, depending on where your doing that).

Hmmmm, a[0]["c"] is prolly the best way, if your dong it from console?

On 25 May 2012 16:10, MANU  wrote:
I've got this result :


> var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1)
> a
{ "_id" : ObjectId("4fbf9bf2ab98db2e62486a3a"), "c" : 15 }


> var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1)
> a[1][c]
Fri May 25 17:08:22 ReferenceError: c is not defined (shell):1


> var a = db.coll.find({},{c:1}).sort({c:-1}).limit(1)
> a[1]["c"]
Fri May 25 17:08:58 TypeError: a[1] has no properties (shell):1

I'd like to do :

>a/3
5


Le vendredi 25 mai 2012 17:00:57 UTC+2, Sammaye a écrit :
No but you can do: a[1][c]

Sam Millman

unread,
May 25, 2012, 11:23:10 AM5/25/12
to mongod...@googlegroups.com
Though do be aware that this behaviour does not transist into all drivers, so in PHP even with a limit one you will get a cursor back.

Just thought I'd let you know incase your banking on this functionality within your server side language.

MANU

unread,
May 25, 2012, 11:38:07 AM5/25/12
to mongod...@googlegroups.com
for the moment I'm currently in the console.

My objective is to compare performance query compare to Oracle's query GROUP BY.

So my second step will be putting my mongo code into a js script and analyse the time spent.

Is it possible to write into a file in javascript in order to store the start date and the end date ?

Dan Crosta

unread,
May 25, 2012, 11:48:20 AM5/25/12
to mongodb-user
You can store the date into a variable using something like:

var start = new Date()
/* do some stuff */
var end = new Date()
print("took " + ((end - start) / 1000) + " seconds");

If you are comparing performance, you may also want to compare against
map-reduce and the aggregation framework. This particular algorithm
(finding the max or min value within a group) can be implemented in
all 3 approaches.

- Dan

MANU

unread,
May 25, 2012, 12:00:29 PM5/25/12
to mongod...@googlegroups.com
Thank you but I don't want to print my result into the log of my console.

I prefer write my results into a log file with some information like the methode, the number of document.

Can I do something like that :

var myFile = document.open()


var start = new Date()
myFile.write(start)


/* do some stuff */
var end = new Date()

myFile.write(end)



Dan Crosta

unread,
May 25, 2012, 12:18:37 PM5/25/12
to mongodb-user
There's no particularly good way to do this from within the MongoDB
shell, but you can redirect the shell's printed output into a file.
For instance, if you are using a Linux-like system, you could do:

mongo host:port/dbname yourScript.js > scriptResults.txt

- Dan

MANU

unread,
May 25, 2012, 12:24:47 PM5/25/12
to mongod...@googlegroups.com
Yes !
you made my day guys ! ;)

thanks for all and have a nice WK
Reply all
Reply to author
Forward
0 new messages