4Z4T4R
4Z4T4R

Reputation: 2458

How to insert document field value as ISODate with Ruby MongoDB driver?

It may be really simple, but the obvious is elusive at the moment in Ruby land.

How do I insert document field value as ISODate and NOT a string with Ruby MongoDB driver? When I query a collection inside the MongoDB shell, I want the timestamp to be an ISODate object:

{
  "_id": ObjectId("570348904b3833000addcd67"),
  "timestamp": ISODate("2016-04-04T21:23:52.058Z")
}

And NOT:

{
  "_id": ObjectId("570348904b3833000addcd67"),
  "timestamp": "2016-04-04T21:23:52.058Z" // or ms since epoch
}

Please don't suggest I use ms|s since epoch. It's not a solution here.

I've tried...

logs = []
t = Time.at(1448064510963.fdiv(1000))
mongo_hash['timestamp'] = t # --> String
mongo_hash[:timestamp] = t # --> String
mongo_hash['timestamp'] = t.to_datetime # --> Weird Date String
mongo_hash['timestamp'] = t.to_date # --> String without time
logs << mongo_hash

I'm pushing mongo_hash into an array that's passed into insert_many.

mongo_client[:logs].insert_many(logs)

...and what I get in MongoDB 3.0.x is a string for the timestamp using Ruby Mongo driver v2.2.4...

{
  "_id": ObjectId("573107ac4f5bd9ac14920bb0"),
  "timestamp": "2015-11-20T11:59:43.127-08:00"
}

Piece of cake in JS/Python... why so weird, Ruby? Whyyyy?

Upvotes: 3

Views: 3123

Answers (1)

mu is too short
mu is too short

Reputation: 434735

I couldn't find any documentation on this but if you look at the official examples, you'll see this:

result = client[:restaurants].insert_one({
  #...
  grades: [
    {
      date: DateTime.strptime('2014-10-01', '%Y-%m-%d'),
      grade: 'A',
      score: 11
    },
    #...
  ]
  #...
})

That would suggest that you can use simple DateTime instances to insert times into MongoDB. So what happens if we try that? Well:

irb>  mongo[:pancakes].insert_one(:kind => 'blueberry', :created_at => DateTime.now)

and then in MongoDB:

> db.pancakes.find()
{ "_id" : ..., "kind" : "blueberry", "created_at" : ISODate("2016-05-15T17:44:12.096Z") }

The ISODate that we want is there.

Then if we pretend we're in Rails:

irb> require 'active_support/all' # To get to_datetime
irb> mongo[:pancakes].insert_one(:kind => 'banana', :created_at => '2016-05-15T06:11:42.235Z'.to_datetime)

we get this inside MongoDB:

> db.pancakes.find()
{ "_id" : ObjectId("5738b56cf638ccf407c71ef5"), "kind" : "blueberry", "created_at" : ISODate("2016-05-15T17:44:12.096Z") }
{ "_id" : ObjectId("5738b74ef638ccf4da4c2675"), "kind" : "banana", "created_at" : ISODate("2016-05-15T06:11:42.235Z") }

ISODates again.

I'm using version 2.2.5 of the official Ruby driver here.

Upvotes: 3

Related Questions