Datatype changes from Int to Float when using group aggregation

344 views
Skip to first unread message

chris

unread,
May 25, 2011, 6:46:33 AM5/25/11
to mongodb-casbah-users
Hi,
I'm trying to use the group aggregation.

I have documents of the following structure in my mongodb:

{ "_id" : ObjectId("4ddcdc9ab4d8a3a90345508e"), "vehicleId" : "1",
"timestamp" : ISODate("2011-05-25T10:40:25.856Z"), "speed" : 1 }
{ "_id" : ObjectId("4ddcdc9ab4d8a3a90345508f"), "vehicleId" : "2",
"timestamp" : ISODate("2011-05-25T10:40:26.232Z"), "speed" : 2 }
[...]

In a test, I want to get the latest speed per vehicleId, i.e. I'm
doing the following:

val key = MongoDBObject("vehicleId" -> true)
val cond = MongoDBObject.empty
val initial = MongoDBObject("timestamp" -> 0)

val reduce =
"""function(doc, prev) {
if (doc.timestamp > prev.timestamp) {
prev.speed = doc.speed;
prev.timestamp = doc.timestamp;
}
}"""

val groupedSpeed = collection.group(key, cond, initial, reduce)

for (dbObject: DBObject <- groupedSpeed) {
println(dbObject.toString)

The weird thing is that in the collection groupedSpeed, the field
speed is not an Int anymore:

{ "vehicleId" : "2" , "timestamp" : { "$date" :
"2011-05-25T10:40:49Z"} , "speed" : 2.0}
{ "vehicleId" : "1" , "timestamp" : { "$date" :
"2011-05-25T10:40:49Z"} , "speed" : 1.0}

Did I miss something?

Cheers,
Christian

Brendan W. McAdams

unread,
May 25, 2011, 1:54:20 PM5/25/11
to mongodb-ca...@googlegroups.com
I've seen this before, it seems to be a side effect of how the MongoDB JavaScript context pulls in numbers to Group and MapReduce.

It seems to almost always output them as Doubles or the like. 

Not a Casbah issue, just be prepared for a slight change in expected output :/

chris

unread,
May 26, 2011, 3:12:39 AM5/26/11
to mongodb-casbah-users
Hi,
thanks for your answer.

I tried the same on the mongo console and there speed stays an Int:

for (var i = 1; i <= 5; i++) {
for (var j = 1; j <= 50; j++) {
db.testcoll.insert({"vehicleId":j, "timestamp":new Date(),
"speed":j})
}
}

db.testcoll.group (
{key: {vehicleId: true},
reduce: function(doc, prev) {
if (doc.timestamp > prev.timestamp) {
prev.vehicleId = doc.vehicleId;
prev.timestamp = doc.timestamp;
prev.speed = doc.speed;
}
},
initial: {timestamp: 0}
})

What do you think about it?

Cheers,
Christian

chris

unread,
May 26, 2011, 3:14:56 AM5/26/11
to mongodb-casbah-users
... forgot to show the query's result:

{
"vehicleId" : 1,
"timestamp" : ISODate("2011-05-26T07:10:24.359Z"),
"speed" : 1
},
{
"vehicleId" : 2,
"timestamp" : ISODate("2011-05-26T07:10:24.359Z"),
"speed" : 2
},

[...]

Scott Hernandez

unread,
May 26, 2011, 3:31:28 AM5/26/11
to mongodb-ca...@googlegroups.com
Those aren't ints, they are doubles; By default all numbers in javascript are double (64bit fp). There is no int (32bit signed value) in javascript at all.
http://www.mongodb.org/display/DOCS/mongo+-+The+Interactive+Shell#mongo-TheInteractiveShell-SomeNotesonDatatypesintheShell
 
If you run a query using the $type option then you will see this, or if you retrieve the value with scala/java/language-with-32/64bit-ints then you will see this also.

Here is a small sample from the mongo (javascript) shell.
>db.capped.insert({_id:1, foo:1})
>db.capped.findOne({foo:{$type:1}}) // 1 = double
{ "_id" : 1, "foo" : 1 }

See the bson spec for more type information. http://bsonspec.org/#/specification
Reply all
Reply to author
Forward
0 new messages