Question

Astyanax supports composite columns in Cassandra through its AnnotatedCompositeSerializer. I have a column family with 3-field composite column names, similar to this example, adapted from Astyanax's documentation (the columns aren't actually sessionId and token, pretend they are for argument's sake):

// Annotated composite class
public class SessionEvent {
  @Component(ordinal=0) UUID sessionId;
  @Component(ordinal=1) UUID token;
  @Component(ordinal=2) UUID timestamp;

  public SessionEvent() { }
}

static AnnotatedCompositeSerializer<SessionEvent> eventSerializer
      = new AnnotatedCompositeSerializer<>(SessionEvent.class);
static ColumnFamily<String, SessionEvent> CF_SESSION_EVENTS
      = new ColumnFamily<>("SessionEvents",
                           StringSerializer.get(), eventSerializer);

// Querying cassandra for a column slice on one prefix, but we want two!
OperationResult<ColumnList<SessionEvent>> result = keyspace.prepareQuery(CF_SESSION_EVENTS)
    .getKey("UserId1")
    .withColumnRange(eventSerializer.buildRange()
        .withPrefix("SessionId1")
        .build())
    .execute();

The problem is: I want to query for all columns with two composite columns (in this case, both sessionId and token) in the prefix, not just one, and for all timestamps, not just within a range. This is clearly possible and easy to do with CQL3, but I'm stuck on Cassandra 1.0.x and can't find a way that Astyanax will accept (by either calling withPrefix(UUID) twice or passing it a composite data structure).

Is there any way to do this with Astyanax? Can I somehow use a basic RangeBuilder and serialize the start and end manually, perhaps?

Was it helpful?

Solution

Columns in Cassandra are stored in order. In your example, sessionId is the most significant, followed by token, and timestamp is the least significant. In other words, columns are sorted by sessionId, then token, then timestamp.

If I understand correctly, you're trying to query for the columns with a specified sessionId as well as token and any time. For the reasons above, the columns with matching sessionId and token are stored contiguously. You can query them with any date by using min/max dates in the following way:

startTime = new Date(0);
endTime = new Date(Long.MAX_VALUE);

SessionEvent from = new SessionEvent(sessionId, token, startTime);
SessionEvent to = new SessionEvent(sessionId, token, endTime);

RangeBuilder rb = new RangeBuilder().setStart(from).setEnd(to);

OperationResult<ColumnList<SessionEvent>> result = keyspace
        .prepareQuery(CF_SESSION_EVENTS)
        .getKey("UserId1")
        .withColumnRange(rb.build())
        .execute();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top