Tuesday, August 3, 2010

Reading keys and columns from a simple column family in a Cassandra dB

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);
         }
       
        
  }
 
}

1 comment:

  1. I think this is one of the most significant information for me.I hope many people will like it.Have a good time!

    Hire iphone app developer

    ReplyDelete