inserting dates into mongodb using vertx-mongo-service

1,150 views
Skip to first unread message

Asher Tarnopolski

unread,
Mar 23, 2015, 11:48:12 AM3/23/15
to ve...@googlegroups.com
hi all,

is it possible to use fields of type date with mongo-service?
e.g. i want a java Date() to be stored as a Date or ISODate in mongo. 

thanks.

Asher Tarnopolski

unread,
Apr 2, 2015, 4:33:32 AM4/2/15
to ve...@googlegroups.com
just bumping this up, since i didn't find a solution yet. 
it seems i'm missing something, did anyone have a chance to do this?

Tim Fox

unread,
Apr 2, 2015, 4:34:31 AM4/2/15
to ve...@googlegroups.com
As usual, please add an issue if it hasn't been resolved yet, so it doesn't get forgotten :)
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Geoffrey Clements

unread,
Apr 2, 2015, 8:22:01 AM4/2/15
to ve...@googlegroups.com
I just used a DateFormat to convert it to/from a string. With all the error checking removed:

dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); 

String s = json.getString("createdOn");
createdOn = dateFormat.parse(s);

json.put("createdOn", dateFormat.format(createdOn));

Have a look at the BaseModel class in this project for more details:



geoff

Asher Tarnopolski

unread,
Apr 2, 2015, 8:31:32 AM4/2/15
to ve...@googlegroups.com

thanks Geoff,
this is what I'm doing now, however the point is to store date fields in mongodb itself as isodate object and not as string. i need to compare dates in different timezones while running queries directly vs mongo.


--
You received this message because you are subscribed to a topic in the Google Groups "vert.x" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/vertx/eMzeufLeCZw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to vertx+un...@googlegroups.com.

Geoffrey Clements

unread,
Apr 2, 2015, 9:18:20 AM4/2/15
to ve...@googlegroups.com
I had a quick look. The underlying serialization library will handle Dates. You just need to extend JsonObject to handle Date (add a put(String key, Date date) method. Then submit a pull request.

I almost suggested a put(String key, Object obj) to handle objects types that JsonObject doesn't handle. But that would lead to ambiguities.

Another possibility is to subclass JsonObject and have it wrap a Date instance and override encode to Json.encode the date rather than the map. (And probably a few other methods.)


geoff

David Bush

unread,
Apr 3, 2015, 8:59:28 AM4/3/15
to ve...@googlegroups.com
Convert your Date to a long with Date.getTime(). Then in your document that goes to Mongodb, create a JSON structure like this through whatever means:

{ "createdOn": { "$date": date_as_long } }

In Groovy I do it like this: 

Map document = [createdOn: ['$date': new Date().getTime()]]

You can also send a string in ISO format, but I prefer Date.getTime() as it is relative to GMT and there is no difficulty in converting timezones.

Even though the date is stored as ISODate in Mongo, when you query the database with the vertx mongo module, the date will come back like this: 

“birth_date”: {“$date”: “2012-12-19T06:00:00.000Z”}}
So, to get a JVM Date object back, you have to get the string from the $date object and parse it back to a date. In Groovy I do it like this:

String date_string = createdOn.'$date'
Date.parse('yyyy-MM-dd'T'HH:mm:ss.SSSZ', date_string)

Asher Tarnopolski

unread,
Apr 3, 2015, 9:14:37 AM4/3/15
to ve...@googlegroups.com

hey david,

actually i already tried to use $date but i got a bson format exception saying it's unhappy with an attempt to use a $ in a key name... it's interesting that this stuff works with groovy, i think I'll dig into this again.

thanks.


--

David Bush

unread,
Apr 4, 2015, 11:32:08 AM4/4/15
to ve...@googlegroups.com
Ok. You made me use Java for the first time in years. :-) Now I remember why I prefer Groovy.

Anyway this test seems to work:


@Test
public void testDate() {

 
JsonObject config = new JsonObject();
 config
.putString("address", "test");
 config
.putBoolean("fake", true);

 container
.deployModule("io.vertx~mod-mongo-persistor~2.1.0", config, new AsyncResultHandler<String>() {
   
@Override
   
public void handle(AsyncResult<String> asyncResult) {
     
if (asyncResult.failed()) {
       container
.logger().error(asyncResult.cause());
     
} else {
       assertTrue
(asyncResult.succeeded());
       assertNotNull
("deploymentID should not be null", asyncResult.result());

       
JsonObject dateField = new JsonObject();
       dateField
.putNumber("$date", new java.util.Date().getTime());

       
JsonObject document = new JsonObject();
       document
.putElement("createdOn", dateField);

       
JsonObject saveEvent = new JsonObject();
       saveEvent
.putString("action", "save");
       saveEvent
.putString("collection", "test");
       saveEvent
.putElement("document", document);

       vertx
.eventBus().send("test", saveEvent, (Handler<Message>) save_reply -> {
         
System.out.println(save_reply.body());
         
JsonObject mongoReply = (JsonObject)save_reply.body();
         assertEquals
("ok", mongoReply.getString("status"));
         testComplete
();
       
});
     
}
   
}
 
});
}



Here's the Groovy version for any Groovyers watching:



 
def eb = vertx.eventBus

 
String id = new org.bson.types.ObjectId().toHexString()
 
EventSequence sequence = new EventSequence()
 sequence
.activity {
   container
.deployModule("io.vertx~mod-mongo-persistor~2.1.0", [address: 'test', fake: true]) { result ->
   
if (result.succeeded) {
     println
"io.vertx~mod-mongo-persistor~2.1.0 has been deployed, deployment ID is ${result.result}"
     sequence
.next()
   
}
   
else {
     println
"io.vertx~mod-mongo-persistor~2.1.0 deployment failed ${result.cause().printStackTrace()}"
     assertTrue
(false)
     sequence
.stop()
     
}
   
}
 
}.activity {
   
Map document = [
     _id
: ['$oid': id],
     create_date
: ['$date': new Date().getTime()]
   
]
   
Map event = [
     action
: 'save',
     collection
: 'test',
     document
: document
   
]
   eb
.send("test", event) { response ->
   assertEquals
("ok", response.body.status)
   sequence
.next()
   
}
 
}.activity {
   
Map event = [
     action
: 'findone',
     collection
: 'test',
     matcher
: [_id: ['$oid': id]]
   
]
   eb
.send("test", event) { response ->
     println response
.body
     
//[result:[_id:[$oid:551fef1ed4c61493bd68c605], create_date:[$date:2015-04-04T14:03:10.400Z]], status:ok]
     assertEquals
("ok", response.body.status)
     assertNotNull
(response.body.result.create_date.'$date')
     testComplete
()
   
}
 
}.execute()




Asher Tarnopolski

unread,
Apr 4, 2015, 12:02:47 PM4/4/15
to ve...@googlegroups.com

hey david, i see you took this challenge seriously :)

i use v3's vertx-mongo-ext and not v2's module, and also converting date to long isn't good enough since it kills the time zone.
as i said, i tried $date with a formatted string, but i got an exception. tomorrow I'll take another look to see where exactly it is thrown from.

thanks anyway!

David Bush

unread,
Apr 4, 2015, 3:03:15 PM4/4/15
to ve...@googlegroups.com
Actually it doesn't kill the time zone.

From Java Date.getTime() API:

Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.

So, the long that getTime() returns is relative to GMT no matter what time zone you create the Date object in. If you and your friend create date objects at the same time (meaning the very same instant in real time with no offset) in Wrocław and Honolulu, getTime() will return the very same long. If you then reconstitute a date object in each time zone from that long, you will get the date you started with in each time zone. 

When you store the date in the way I mentioned, Mongo will save it as an ISODate using the same definition as the Java Date class. If you query the database from the command line, you will see that the date returned is equal to the date you saved in your time zone. The time zone has not been lost.

I'm using Vert.x for quantitative stock trading and consuming a massive number of events. The time at which certain events happen is very important to me. So, I've been through all of this with Mongo and Mysql. I initially assumed the same thing as you regarding the time zone. Luckily, that has turned out to be false and dealing with longs makes my life much easier. 

It's probably best to prove it to yourself with a simple test. That's what I did, and it works!

Perhaps v3 has changed the way it handles mongo data types. I haven't (ad)ventured into that yet.

Asher Tarnopolski

unread,
Apr 5, 2015, 3:21:11 AM4/5/15
to ve...@googlegroups.com
hey david,

this is very interesting. you r totally right re timezone / date representation through long stuff. somehow i didn't think about it this way.
i just took another look at my problem in mongo and i see that bson exception is actually thrown from the  new mongo async driver used in v3 mongo-ext. 
it validates all json keys and doesn't allow $ char at pos 0. 

cheers,
asher

Tim Fox

unread,
Apr 13, 2015, 6:24:29 AM4/13/15
to ve...@googlegroups.com
On 04/04/15 16:32, David Bush wrote:
Ok. You made me use Java for the first time in years. :-) Now I remember why I prefer Groovy.

Anyway this test seems to work:


@Test
public void testDate() {

 
JsonObject config = new JsonObject();
 config
.putString("address", "test");
 config
.putBoolean("fake", true);

 container
.deployModule("io.vertx~mod-mongo-persistor~2.1.0", config, new AsyncResultHandler<String>() {
   
@Override
   
public void handle(AsyncResult<String> asyncResult) {

Using anonymous classes in Java 8 like this is unnecessary, as Java 8 has support for lambdas (A bit like closures in Groovy) :)

You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages