您的位置:首页 > 其它

Cassandra 使用Thrift API 操作数据简例--读写单行单列数据

2013-02-24 18:51 519 查看
前些日子刚刚做了一些实验,由于API更改也是很迅速的,很多方法忽然的被淘汰,甚至参数类型都有变化,所以记录下

cassandra 1.2.1 使用Thrift api操作数据的几个例子, 以备自查

cassandra 不同于 RDBMS 查询数据需要了解两个概念 Range 和 Slice

Range 指行范围, Cassandra的行是按照一定的顺序存储在硬盘上的, Range值截取其中的一部分

行的排序在建立column families 的时候用comparator 来指定

Slice 指列切片, 由于列也是按顺序存放的, 所以可以取出某一部分列,在代码中可以指定, 比如a b c d e 五列, 我取出 a到c 就可以取出a b c列

1, 简单的写操作

要操作cassandra数据库,需要写代码指定IP 端口打开数据库,这里假设有一个client 客户端实例,我们只记录下写数据的代码

Cassandra.Client client=conn.connect("Keyspace1"); //连结数据库的的 Keyspace1

String cfName="Standard"; //指定column families 的名字 "Standard"
long timestamp=System.currentTimeMillis(); //时间戳
byte[] userIDKey="1".getBytes(); // rowkey 相当于 primary key ,写数据的时候需要指定rowkey

colPathName.setColumn("name".getBytes(UTF8));
// 查询哪个单元列呢? 指定列名, 列名是 byte[] 类型

ColumnParent cp=new ColumnParent(cfName);
//把含有column families 的str传入这个类 cp用来插入数据的时候插入那个cf

//Insert the name column
LOG.info("Inserting row for key "+ new String(userIDKey));
//要插入一列, 建立一个列对象
Column nameCol=new Column();
nameCol.setName("name".getBytes(UTF8)); //设置列名
nameCol.setValue("George Clinton".getBytes());//设置列名对应的值key-value
nameCol.setTimestamp(timestamp);//设置时间戳
client.insert(UsefulUtils.toByteBuffer(userIDKey),cp,nameCol,CL);
//插入,需要四个元素,1,Bytebuffer格式的rowkey,(老版本是byte[],我了个小方法把byte转化为ByteBuffer,
//这个例子是书上的,. 2,cp,指定是那个表(column familie),3 nameCol, 指定是那个列, 4,CL 一致性级别
//CL是我定义的常量 Consistency.ONE)

//insert age column
LOG.info("Inserting row for key "+ new String(userIDKey));
Column ageCol=new Column();
ageCol.setName("age".getBytes(UTF8));
ageCol.setValue("69".getBytes(UTF8));
ageCol.setTimestamp(timestamp);
client.insert(UsefulUtils.toByteBuffer(userIDKey),cp,ageCol,CL);//插入第二列
//这个例子我们总共插入了两列, name="George Clinton" age=69  rowkey=1
//至此数据已经插入完成 下面是查询

LOG.info("Row insert done");

ColumnPath colPathName=new ColumnPath(cfName);  // 这个是用来查询一单元列数据用这个ColumnPath
//read the name only
Column col=client.get(UsefulUtils.toByteBuffer(userIDKey), colPathName, CL).getColumn();
//查询的时候需要指定: 1 rowkey 2 Columnpathname 3 一致性级别. 使用client.get得到一个Column对象
//然后可以用col.name col.value 分别得到名字, 和值 得到的对象是bytebuffer类型,需要转换成string
LOG.info("Column name :"+ UsefulUtils.toString(col.name));
LOG.info("Column value :"+ UsefulUtils.toString(col.value));
LOG.info("Column timestamp :"+ timestamp);

//create a slice predicate representing the columns to read start and finish
//用来查询一个区间(多行)

SlicePredicate predicate =new SlicePredicate();//定义一个查询切片的 谓词
SliceRange sliceRange=new SliceRange();// 定义一个需要查询的列切片 , 这个切片要传入谓词
sliceRange.setStart("age".getBytes()); //切片开始
sliceRange.setFinish("name".getBytes());//切片结束
//这里setStart定义了一个开始区间, setFinish定义一个结束的区间, 这个区间可以想象成一个表列的顺序
//比如我们有 age email name sex 是这样的顺序, age -name 就会取出来 a e n散列, sex就被过滤掉了
//取出全部列可以把开始结束定义为 "0".getbytes() . 某种意义上是指定select columns from table,但是这个
//columns只能是区间,因为cassandra 的列是有顺序的,这个排序方法是自己在建立表(column families)的时候就定义的.
predicate.setSlice_range(sliceRange);//把定义好的一个列切片(from age to name)传入切片谓词 使用setSlice_range()

LOG.info("Complete Row:");

//read all columns in the row 这里读出所有列,刚才我们定义的切片
ColumnParent parent =new ColumnParent(cfName); //有了切片,我们从那个columnfamlie查询这个列, 也要事先定义.
List<ColumnOrSuperColumn> results=client.get_slice(UsefulUtils.toByteBuffer(userIDKey), parent, predicate, CL);
//使用client,get_slice来得到切片,返回值是一个List<ColumnOrSuperColumn>类型,是普通列或者超列.我们这里是普通咧
// 指定四个参数 1 读取哪个rowkey的列切片(where id='1') 2, 从那个列族读 (select from table),3 查询谓词select columns(from na		//me to email) 4,一致性级别 ONE, 只要写入一个服务器就算成功,我只有一个节点);
//loop over columns,outputting values.
//我们得到一个一行(rowkey指定) 的所有列 (指定的切片的列) 然后遍历这些columns
for (ColumnOrSuperColumn result : results){
Column column =result.column;// 定义column, 用resule.column遍历results
//挨个输出column的键和值
LOG.info(UsefulUtils.toString(column.name) +":" +UsefulUtils.toString(column.value));
}
conn.close();
LOG.info("all DONE");


到这里,我们看到了如何插入一个行, 其实应该是插入属于某个rowkey 的 几列 比如rowkey=1 name='' age='' cassandra的好处在于,你不用实现指定这个行有多少列, 你只管指定一个rowkey=2, 然后列名随便取一个,你也会成功的, 所以说cassandra是无schema的, 第一行的列可以跟第二行完全不同,一行可以有几万个列都不成问题.

然后读取一行数据, 需要指定读取哪一行 rowkey, 然后读取那一列或者几列,

如果只读取一列,用columnpath,把列族名传入,调用client.get方法,传入四个参数就可以搞定

如果读取一行多列数据,用 columnparent指定表名, 定义Slicerange指定列范围(开始结束), 然后把slicerange传入切片谓词predicate, 然后调用client.get_slice(rowkey,包含表名的parent,谓词,一致性级别) 就能得到包含对应这个rowkey的所有columns. 使用getname getvalue能得到名字和值

如何查询多行数据,查看下一篇
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: