[CSHARP-377] Add an ObjectID constructor that takes a DateTime and optionally a Highest/Lowest Bool Created: 06/Jan/12  Updated: 02/Apr/15  Resolved: 06/Jan/12

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 1.3.1
Fix Version/s: 1.4

Type: New Feature Priority: Minor - P4
Reporter: Mathias Stearn Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible

 Description   

This makes it easier to construct queries for things like find all objects created yesterday



 Comments   
Comment by Robert Stam [ 06/Jan/12 ]

The ObjectId class is immutable, so making the CreationTime support a setter is a no-go.

Here's the design I'm going with. It integrates well with the existing methods. The design insight is that DateTime is just a way of expressing the timestamp in different units, so we just need a few new overloads. To support generating back-dated ObjectIds we just need a few more overloads of the existing GenerateNewId factory method.

Here's what the design looks like:

public ObjectId(DateTime timestamp, int machine, short pid, int increment); // new overload
public ObjectId(int timestamp, int machine, short pid, int increment); // existing overload
 
public static ObjectId GenerateNewId(); // existing overload
public static ObjectId GenerateNewId(DateTime timestamp); // new overload
public static ObjectId GenerateNewId(int timestamp); // new overload

The sample code I provided earlier would now look like this (only the creation of the ObjectIds has changed):

// example: find all documents created on 2011-12-01
var firstObjectId = new ObjectId(new DateTime(2011, 12, 1), 0, 0, 0);
var lastObjectId = new ObjectId(new DateTime(2011, 12, 2), 0, 0, 0);
var query = Query.And(
    Query.GTE("_id", firstObjectId),
    Query.LT("_id", lastObjectId)
);
foreach (var document in collection.Find(query))
{
    // process document created on 2011-12-01
};

Comment by Mathias Stearn [ 06/Jan/12 ]

I personally prefer constructors for making objects, but I'm not a C# developer so I don't really know what is idiomatic there. Either way the actual syntax isn't important, just that there is a user-friendly way to construct objects.

The low/high bool isn't really necessary, although the java behavior is interesting. Could this be achieved by making the CreationTime property support a setter?

Comment by Robert Stam [ 06/Jan/12 ]

Can you be more precise on what the highest/lowest bool means? I'm guessing it means use all zeroes or all ones for the rest of the ObjectId.

Since we're not constructing "legal" ObjectIds and ObjectId already has a property called CreationTime, I would propose a static factory method called FromCreationTime instead of a new constructor. For example:

// example: find all documents created on 2011-12-01
var firstObjectId = ObjectId.FromCreationTime(new DateTime(2011, 12, 1));
var lastObjectId = ObjectId.FromCreationTime(new DateTime(2011, 12, 2));
var query = Query.And(
    Query.GTE("_id", firstObjectId),
    Query.LT("_id", lastObjectId)
);
foreach (var document in collection.Find(query))
{
    // process document created on 2011-12-01
};

By using an closed/open range on the query I don't think there is any need for a highest/lowest bool parameter.

FYI: The Python and Ruby drivers also have factory methods for this (named from_datetime and from_time respectively). The Java driver has a constructor that takes a Date but it can't really be used for this purpose because instead of zeros for the rest of the ObjectId it fills in real values for the machine/pid/inc fields. What the Java driver does is useful for creating backdated ObjectIds, so maybe there is some more design work to do here to cover both cases (range searching and backdating).

Generated at Wed Feb 07 21:36:39 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.