In the first part of these posts I’m going to look at retrieving data from a Cassandra Keyspace. We are working with the BloggyAppy design from
Arin Sarkissian and the code is heavily based on the Hector examples at
Wiki.
First up lets look at getting the author details from the Authors ColumnFamily. So assuming we have a pool of connections from the Hector pool called “client” we can set the Column Family like this :
Keyspace ks = client.getKeyspace("BloggyAppy");
//retrieve sample data
ColumnParent columnParent = new ColumnParent("Authors");
We are going to use the getRangeSlice method from the KeySpace class to search for a single Author or to list all Author details. This requires a ColumnParent (set above) a slicePredicate and a KeyRange. The keyRange is used to limit the number of keys that are returned and to limit the keysearch to a certain range. The code looks like this:
KeyRange keyRange = new KeyRange();
keyRange.setStart_key(“”);
keyRange.setEnd_key("");
These settings will get all Keys in the Keyspace. If you want to limit the number you can put a numerical value in the KeyRange constructor:
KeyRange keyRange = new KeyRange(1);
This will get just one result. If you want to look for one Key only (such as the Author Andy) then you can do this:
KeyRange keyRange = new KeyRange(1);
keyRange.setStart_key(“Andy”);
keyRange.setEnd_key("");
Hopefully you can see that:
KeyRange keyRange = new KeyRange(100);
keyRange.setStart_key(“Andy”);
keyRange.setEnd_key("Dave");
Will get at most 100 keys that are between the “Andy” and “Dave”
So we can see how to restrict the number of keys that are returned. We now need to look at limiting the number of columns from the requested key are returned. Suppose we have the following
Andy
Tel == 01382 345078
Email == andy@r2-dvd.org
Address == QMB
We may only need the first column (Tel) or all columns or a slice range in between. We will use a slice range (that looks a lot like the keyRange !)
SliceRange columnRange = new SliceRange();
columnRange.setCount(4);
columnRange.setStart(new byte[0]);
columnRange.setFinish(new byte[0]);
columnRange.setReversed(true);
Some differences to note here we can change the order of that the columns are returned using setReversed. The start and end of the column Range are byte arrays (so that the columns need note be strings in the dB) If you want to search for a string (if that makes sense in your app) you can do this of course:
String start="Email";
byte bStart[]=start.getBytes();
columnRange.setStart(bStart);
Finally we can create a slicePredicate form the columnRange and get the keys and columns from the keySpace.
SlicePredicate slicePredicate = new SlicePredicate(); slicePredicate.setSlice_range(columnRange);
Map<String, List<Column>> map = ks.getRangeSlices(columnParent, slicePredicate, keyRange);
Now we’ve got the map, we’ll just read through it and display the columns:
for (String key : map.keySet()) {
List<Column>
columns = map.get(key);
//print key
System.out.println(key);
for (Column column : columns) {
//print columns with values
System.out.println("\t" + string(column.getName()) + "\t ==\t" + string(column.getValue()));
}
}
This should be all we need to get “records” from a simple column family inside a keyspace.
If we want to get all posts by a particular author all we need to do is use our AuthorPosts Column family and use the above code to display the details for each post. Here’s my complete code for displaying all posts for Author “Andy”:
public class ReadAuthorPosts {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
CassandraClientPool pool = CassandraClientPoolFactory.INSTANCE.get();
CassandraClient client = pool.borrowClient("xxx.yy.36.151", 9160);
try {
Keyspace ks = client.getKeyspace("BloggyAppy");
//retrieve sample data
ColumnParent columnParent = new ColumnParent("AuthorPosts");
SlicePredicate slicePredicate = new SlicePredicate();
/**
* this effect how many columns we are want to retrieve
* also check slicePredicate.setColumn_names(java.util.List<byte[]> column_names)
* .setColumn_names(new ArrayList<byte[]>()); no columns retrievied at all
*/
SliceRange columnRange = new SliceRange();
String Start="s";
//For these beware of the reversed state
//columnRange.setStart(Start.getBytes()); //Sets the first column name to get
columnRange.setStart(new byte[0]); //We'll get them all.
columnRange.setFinish(new byte[0]); //Sets the last column name to get
//effect on columns order
columnRange.setReversed(false); //Changes order of columns returned in keyset
columnRange.setCount(1000); //Maximum number of columsn in a key
slicePredicate.setSlice_range(columnRange);
//count of max retrieving keys
KeyRange keyRange = new KeyRange(1); //Maximum number of keys to get
keyRange.setStart_key("Andy");
keyRange.setEnd_key("");
Map<String, List<Column>> map = ks.getRangeSlices(columnParent, slicePredicate, keyRange);
//printing keys with columns
for (String key : map.keySet()) {
List<Column> columns = map.get(key);
//print key
System.out.println(key);
for (Column column : columns) {
//print columns with values
java.util.UUID Name=toUUID(column.getName()) ;
System.out.println("\t" + Name + "\t ==\t" + string(column.getValue()));
DisplayPost(string(column.getValue()));
}
}
// This line makes sure that even if the client had failures and recovered, a correct
// releaseClient is called, on the up to date client.
client = ks.getClient();
} finally {
pool.releaseClient(client);
}
}
public static java.util.UUID toUUID( byte[] uuid )
{
long msb = 0;
long lsb = 0;
assert uuid.length == 16;
for (int i=0; i<8; i++)
msb = (msb << 8) | (uuid[i] & 0xff);
for (int i=8; i<16; i++)
lsb = (lsb << 8) | (uuid[i] & 0xff);
long mostSigBits = msb;
long leastSigBits = lsb;
com.eaio.uuid.UUID u = new com.eaio.uuid.UUID(msb,lsb);
return java.util.UUID.fromString(u.toString());
}
private static void DisplayPost(String sKey){
CassandraClientPool pool = CassandraClientPoolFactory.INSTANCE.get();
CassandraClient client=null;
try{
client = pool.borrowClient("xxx.yy.36.151", 9160);
HashMap hm = new HashMap();
hm.put("pubDate", "");
Keyspace ks = client.getKeyspace("BloggyAppy");
//retrieve sample data
ColumnParent columnParent = new ColumnParent("BlogEntries");
SlicePredicate slicePredicate = new SlicePredicate();
/**
* this effect how many columns we are want to retrieve
* also check slicePredicate.setColumn_names(java.util.List<byte[]> column_names)
* .setColumn_names(new ArrayList<byte[]>()); no columns retrievied at all
*/
SliceRange columnRange = new SliceRange();
String Start="s";
//For these beware of the reversed state
//columnRange.setStart(Start.getBytes()); //Sets the first column name to get
columnRange.setStart(new byte[0]); //We'll get them all.
columnRange.setFinish(new byte[0]); //Sets the last column name to get
//effect on columns order
columnRange.setReversed(false); //Changes order of columns returned in keyset
columnRange.setCount(10); //Maximum number of columsn in a key
slicePredicate.setSlice_range(columnRange);
//count of max retrieving keys
KeyRange keyRange = new KeyRange(200); //Maximum number of keys to get
keyRange.setStart_key(sKey);
keyRange.setEnd_key(sKey);
Map<String, List<Column>> map = ks.getRangeSlices(columnParent, slicePredicate, keyRange);
//printing keys with columns
for (String key : map.keySet()) {
List<Column> columns = map.get(key);
//print key
System.out.println(key);
for (Column column : columns) {
//print columns with values
String Name=string(column.getName()) ;
System.out.println("\t" + Name + "\t ==\t" + string(column.getValue()));
}
}
// This line makes sure that even if the client had failures and recovered, a correct
// releaseClient is called, on the up to date client.
client = ks.getClient();
}catch(Exception et){
System.out.println("Can't connect to server "+et);
return;
}
try{
pool.releaseClient(client);
}catch(Exception et){
System.out.println("Can't release pool "+et);
}
}
}