I'm new to cassandra and hector so i'm trying to execute cql queries but the problem is that not all columns are of type string so how dow I execute the query "select * from users"?
My column family looks like this:
UPDATE COLUMN FAMILY users
WITH comparator = UTF8Type
AND key_validation_class=UTF8Type
AND column_metadata = [
{column_name: full_name, validation_class: UTF8Type}
{column_name: email, validation_class: UTF8Type}
{column_name: state, validation_class: UTF8Type, index_type: KEYS}
{column_name: gender, validation_class: UTF8Type}
{column_name: birth_year, validation_class: LongType, index_type: KEYS}
{column_name: education, validation_class: UTF8Type}
];
I use the following code to execute the query:
CqlQuery<String, String, String> cqlQuery = new CqlQuery<String, String, String>(Keyspace,stringSerializer,stringSerializer,stringSerializer);
cqlQuery.setQuery("select * from users");
QueryResult<CqlRows<String, String, String>> result = cqlQuery.execute();
if (result != null && result.get() != null) {
List<Row<String, String, String>> list = result.get().getList();
for (Row row : list) {
System.out.println(".");
List columns = row.getColumnSlice().getColumns();
for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
HColumn column = (HColumn) iterator.next();
System.out.print(column.getName() + ":" + column.getValue()
+ "\t");
}
System.out.println("");
}
}
But because of the 'birth_year' column with validation class Long I can't get the value. I get the following result assuming that there is only one record:
KEY:Carl birth_year: 'strange chars?' full_name:Carl Smith gender:M eduction:electrician state:LA
If I change my query to this:
CqlQuery<String, String, Long> cqlQuery = new CqlQuery<String, String, Long>
TutorialBase.tutorialKeyspace, stringSerializer, stringSerializer, longSerializer);
cqlQuery.setQuery("select birth_year from users");
Than it works.
So how can I do this with only one query and what if I have more datatypes like booleans and floats in the rows of a column family?
Native types. The native types supported by CQL are: native_type::= ASCII | BIGINT | BLOB | BOOLEAN | COUNTER | DATE | DECIMAL | DOUBLE | DURATION | FLOAT | INET | INT | SMALLINT | TEXT | TIME | TIMESTAMP | TIMEUUID | TINYINT | UUID | VARCHAR | VARINT.
CQL provides the facility of using Collection data types. Using these Collection types, you can store multiple values in a single variable.
You specify the value type as String in the CqlRows, so every value is expected to be a string. Because you want to mix Value types, you should keep the column metadata, but also specify the default validation class as BytesType in the schema and then use ByteBuffer as the type in CqlRows:
QueryResult<CqlRows<String, String, ByteBuffer>> result = cqlQuery.execute();
Then, when processing the values, you will have to convert to the appropriate type, and instead of iterating through the columns, you will probably get the specific column by name:
ColumnSlice<String, ByteBuffer> slice = row.getColumnSlice();
HColumn<String,ByteBuffer> col = slice.getColumnByName("birth_year");
System.out.println(" birth_year: " + col.getValue().getLong());
Of course, Strings have to be handled differently, using java.nio.charset.Charset:
Charset.defaultCharset().decode(col.getValue()).toString()
You can determine types from the Column meta-data, but I've only done this via the Thrift API (see ColumnDef), so not sure how to do it via Hector API. But HColumn does provide a getValueSerializer() method, so that could be a start.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With