RejectedSoftware Forums

Sign up

How to insert/update a BsonDate?

Hi!

I'm inserting a moderately complex document into MongoDB (with subdocuments, lists, etc) so I'm creating a string and using insert(parseJsonString(myString)). I'm having problems trying to insert a BsonDate object this way.

I first tried to do (simplified example):

string jsonStr;
auto bsonDate = BsonDate(to!DateTime(Clock.currTime));
jsonStr = format(`{"somefield: "somevalue, "dateobject": %s}`, bsonDate.toString);
mongodb["mycollection"].insert(jsonStr);

This generates this string:

{"somefield": "somevalue", "dateobject": "2014-05-01T21:07:54Z"}

But "dateobject" is inserted as a string into MongoDB. So next I tried:

jsonStr = format(`{"somefield": "somevalue", "dateobject": ISODate("%s")}`), bsonDate.toString);

This time the string is:

{"somefield": "somevalue, "dateobject": ISODate("2014-03-18T14:07:30Z")}

This works with the Mongo console, but the API gives me a runtime error:

std.json.JSONException@std/json.d(804): JSON format error at byte 15: Expected valid json token, got '32ISODate("201'.

Then I thought about inserting the document and doing an update, but if I use update() with an array it unset all the other fields but if I try to use a json String to use $set I've the same problem.

How could I do this?

Another question: is there any way to get the WriteResult after doing an insertion (or just getting the _id) without doing a call to find() next?

Re: How to insert/update a BsonDate?

Oh, I'm dumb, I just noticed that ISO Dates can be compared for date ranges as strings, so problem solved :)

On Thu, 19 Jun 2014 08:21:59 GMT, Juanjo Alvarez wrote:

Hi!

I'm inserting a moderately complex document into MongoDB (with subdocuments, lists, etc) so I'm creating a string and using insert(parseJsonString(myString)). I'm having problems trying to insert a BsonDate object this way.

I first tried to do (simplified example):

string jsonStr;
auto bsonDate = BsonDate(to!DateTime(Clock.currTime));
jsonStr = format(`{"somefield: "somevalue, "dateobject": %s}`, bsonDate.toString);
mongodb["mycollection"].insert(jsonStr);

This generates this string:

{"somefield": "somevalue", "dateobject": "2014-05-01T21:07:54Z"}

But "dateobject" is inserted as a string into MongoDB. So next I tried:

jsonStr = format(`{"somefield": "somevalue", "dateobject": ISODate("%s")}`), bsonDate.toString);

This time the string is:

{"somefield": "somevalue, "dateobject": ISODate("2014-03-18T14:07:30Z")}

This works with the Mongo console, but the API gives me a runtime error:

std.json.JSONException@std/json.d(804): JSON format error at byte 15: Expected valid json token, got '32ISODate("201'.

Then I thought about inserting the document and doing an update, but if I use update() with an array it unset all the other fields but if I try to use a json String to use $set I've the same problem.

How could I do this?

Another question: is there any way to get the WriteResult after doing an insertion (or just getting the _id) without doing a call to find() next?

Re: How to insert/update a BsonDate?

On Thu, 19 Jun 2014 08:21:59 GMT, Juanjo Alvarez wrote:

Hi!

I'm inserting a moderately complex document into MongoDB (with subdocuments, lists, etc) so I'm creating a string and using insert(parseJsonString(myString)). I'm having problems trying to insert a BsonDate object this way.

I first tried to do (simplified example):

string jsonStr;
auto bsonDate = BsonDate(to!DateTime(Clock.currTime));
jsonStr = format(`{"somefield: "somevalue, "dateobject": %s}`, bsonDate.toString);
mongodb["mycollection"].insert(jsonStr);

This generates this string:

{"somefield": "somevalue", "dateobject": "2014-05-01T21:07:54Z"}

But "dateobject" is inserted as a string into MongoDB. So next I tried:

jsonStr = format(`{"somefield": "somevalue", "dateobject": ISODate("%s")}`), bsonDate.toString);

This time the string is:

{"somefield": "somevalue, "dateobject": ISODate("2014-03-18T14:07:30Z")}

This works with the Mongo console, but the API gives me a runtime error:

std.json.JSONException@std/json.d(804): JSON format error at byte 15: Expected valid json token, got '32ISODate("201'.

Then I thought about inserting the document and doing an update, but if I use update() with an array it unset all the other fields but if I try to use a json String to use $set I've the same problem.

How could I do this?

JSON only supports the basic types bool, long, double, string, arrays and dictionaries, so there is no way to represent a date directly with it. To use the full range of BSON types, there are two main ways to go:

  • The fast and memory efficient way is to define a struct that matches the data and insert that (it will be directly serialized to BSON):

    struct MyCollectionEntry {
        string somefield;
        SysTime dateobject; // BsonDate works as well
    }
    auto entry = MyCollectionEntry("somevalue", Clock.currTime());
    mycollection.insert(entry);
    

    See also the "Functions" section of vibe.data.serialization for some attributes that can be used to customize how the data is serialized.

  • Assemble a Bson value directly (less efficient, but more flexible):

    auto entry = Bson.emptyObject;
    entry["somefield"] = "somevalue";
    entry["dateobject"] = BsonDate(Clock.currTime());
    mycollection.insert(entry);
    

Another question: is there any way to get the WriteResult after doing an insertion (or just getting the _id) without doing a call to find() next?

If you use BsonObjectID as the _id, then the best approach is to generate it on the client using BsonObjectID.generate() to avoid the need for a full server round trip. generate() is designed in a way that avoids duplicate IDs when multiple clients generate IDs at the same time for this purpose.

AFAIK, the protocol doesn't send anything back after an insert operation, the way to get status information is to do a getLastError request directly afterwards (or use the safe flag in the client settings), and I'm not sure if the response to that contains the ID.

Re: How to insert/update a BsonDate?

On Thu, 19 Jun 2014 11:14:20 GMT, Sönke Ludwig wrote:

JSON only supports the basic types bool, long, double, string, arrays and dictionaries, so there is no way to represent a date directly with it. To use the full range of BSON types, there are two main ways to go:

I knew about JSON but being new to MongoDB for some reason I tough it would add new types over the JSON basic ones, like a Data type (MongoDB is my first NoSQL experience).

  • The fast and memory efficient way is to define a struct that matches the data and insert that (it will be directly serialized to BSON):
    struct MyCollectionEntry {
        string somefield;
        SysTime dateobject; // BsonDate works as well
    }
    auto entry = MyCollectionEntry("somevalue", Clock.currTime());
    mycollection.insert(entry);
    

    See also the "Functions" section of vibe.data.serialization for some attributes that can be used to customize how the data is serialized.

That's pretty cool, I was already organizing most of my data into structs anyway.

Another question: is there any way to get the WriteResult after doing an insertion (or just getting the _id) without doing a call to find() next?

If you use BsonObjectID as the _id, then the best approach is to generate it on the client using BsonObjectID.generate()

That'll do it.

Thanks for your reply,

Juanjo