Question

What C# type is equivalent to the timeuuid in the Datastax Cassandra C# driver?

I am writing a simple user tracking service and want to access the most latest user history. I am trying to create a table equivalent to this create statement:

CREATE TABLE IF NOT EXISTS user_history (
    user_id text,
    event_type text,
    create_date timeuuid,
    item_id text,
    PRIMARY KEY ((user_id, event_type), create_date)
);

I have made the following class:

[AllowFiltering]
[Table("user_history")]
public class UserHistory
{
    [PartitionKey(1)]
    [Column("user_id")]
    public string UserID;

    [PartitionKey(2)]
    [Column("event_type")]
    public string EventType;

    [ClusteringKey(1)]
    [Column("create_date")]
    public DateTime CreateDate { get; set; }

    [Column("item_id")] 
    public string ItemID;
}

And I am using this statement to create the table in Cassandra:

var table = Session.GetTable<UserHistory>();
table.CreateIfNotExists();

But this gives me the following table:

CREATE TABLE user_history (
  user_id text,
  event_type text,
  create_date timestamp,
  item_id text,
  PRIMARY KEY ((user_id, event_type), create_date)
)

As you can see, the type of create_date is timestamp instead of timeuuid.

I have tried Guid instead of DateTime, but that gives me an uuid when I am calling .CreateIfNotExists().

Should I use Guid instead of DateTime for the CreateDate and create the table explicit using raw CQL3? I guess this will allow me to read and write timeuuid from/to Cassandra (using the GuidGenerator found in the FluentCassandra project)?! (Recall: I am using the Datastax driver)

Was it helpful?

Solution

Timeuuid is basically a guid and so you should use a guid, the following code is taken from here: creating-a-time-uuid-guid-in-net and is part of the FluentCassandra project

"Below is all the code you need to generate a Time UUID or Time-Based Guid object in .NET. "

public static Guid GenerateTimeBasedGuid(DateTime dateTime)  
{
    long ticks = dateTime.Ticks - GregorianCalendarStart.Ticks;

    byte[] guid = new byte[ByteArraySize];
    byte[] clockSequenceBytes = BitConverter.GetBytes(Convert.ToInt16(Environment.TickCount % Int16.MaxValue));
    byte[] timestamp = BitConverter.GetBytes(ticks);

    // copy node
    Array.Copy(Node, 0, guid, NodeByte, Node.Length);

    // copy clock sequence
    Array.Copy(clockSequenceBytes, 0, guid, GuidClockSequenceByte, clockSequenceBytes.Length);

    // copy timestamp
    Array.Copy(timestamp, 0, guid, 0, timestamp.Length);

    // set the variant
    guid[VariantByte] &= (byte)VariantByteMask;
    guid[VariantByte] |= (byte)VariantByteShift;

    // set the version
    guid[VersionByte] &= (byte)VersionByteMask;
    guid[VersionByte] |= (byte)((int)GuidVersion.TimeBased << VersionByteShift);

    return new Guid(guid);
}

OTHER TIPS

Sounds like you solved your problem by creating the table manually.

For people in the future looking for this information, since we don't have a native type in the BCL to represent a TimeUUID like Java, the 2.1.3 version of DataStax .NET Driver introduced a TimeUuid struct to help with this scenario. You can find the source here. It's got an implicit conversion to/from System.Guid and should work with the LINQ driver's table creation methods if you use it as the return Type for a property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top