问题
I tried to run the demo on http://www.riptano.com/blog/whats-new-cassandra-07-secondary-indexes programatically, but the results are different from running it in CLI. It seems like Cassandra can only index columns after index is added. All previous data are left unindexed.
Full source code are as below:-
public static void main(String[] args) {
try {
try {
transport.open();
} catch (TTransportException ex) {
Logger.getLogger(IndexLaterTest.class.getName()).log(Level.SEVERE, null, ex);
System.exit(1);
}
KsDef ksDef = new KsDef();
ksDef.name = KEYSPACE_NAME;
ksDef.replication_factor = 1;
ksDef.strategy_class = "org.apache.cassandra.locator.SimpleStrategy";
CfDef cfDef = new CfDef(KEYSPACE_NAME, COLUMN_FAMILY_NAME);
cfDef.comparator_type = "UTF8Type";
ColumnDef columnDef = new ColumnDef(ByteBuffer.wrap(FULL_NAME.getBytes()), "UTF8Type");
cfDef.addToColumn_metadata(columnDef);
ColumnDef columnDef1 = new ColumnDef(ByteBuffer.wrap(BIRTH_DATE.getBytes()), "LongType");
columnDef1.index_type = IndexType.KEYS;
cfDef.addToColumn_metadata(columnDef1);
ksDef.cf_defs = Arrays.asList(cfDef);
try {
client.system_add_keyspace(ksDef);
client.set_keyspace(KEYSPACE_NAME);
ColumnParent columnParent = new ColumnParent();
columnParent.column_family = COLUMN_FAMILY_NAME;
Column column = new Column(ByteBuffer.wrap(FULL_NAME.getBytes()), ByteBuffer.wrap("Brandon Sanderson".getBytes()), System.currentTimeMillis());
client.insert(ByteBuffer.wrap("bsanderson".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.name = ByteBuffer.wrap(BIRTH_DATE.getBytes());
column.value = ByteBuffer.allocate(8).putLong(1975);
client.insert(ByteBuffer.wrap("bsanderson".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.name = ByteBuffer.wrap(FULL_NAME.getBytes());
column.value = ByteBuffer.wrap("Patrick Rothfuss".getBytes());
client.insert(ByteBuffer.wrap("prothfuss".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.name = ByteBuffer.wrap(BIRTH_DATE.getBytes());
column.value = ByteBuffer.allocate(8).putLong(1973);
client.insert(ByteBuffer.wrap("prothfuss".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.name = ByteBuffer.wrap(FULL_NAME.getBytes());
column.value = ByteBuffer.wrap("Howard Tayler".getBytes());
client.insert(ByteBuffer.wrap("htayler".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.name = ByteBuffer.wrap(BIRTH_DATE.getBytes());
column.value = ByteBuffer.allocate(8).putLong(1968);
client.insert(ByteBuffer.wrap("htayler".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.name = ByteBuffer.wrap(STATE.getBytes());
column.value = ByteBuffer.wrap("WI".getBytes());
client.insert(ByteBuffer.wrap("prothfuss".getBytes()), columnParent, column, ConsistencyLevel.ONE);
column.value = ByteBuffer.wrap("UT".getBytes());
client.insert(ByteBuffer.wrap("htayler".getBytes()), columnParent, column, ConsistencyLevel.ONE);
KsDef ks = client.describe_keyspace(KEYSPACE_NAME);
cfDef = new CfDef(ks.cf_defs.get(0));
ColumnDef columnDef2 = new ColumnDef(ByteBuffer.wrap(STATE.getBytes()), "UTF8Type");
columnDef2.index_type = IndexType.KEYS;
cfDef.setColumn_metadata(Arrays.asList(columnDef, columnDef1, columnDef2));
client.system_update_column_family(cfDef);
Thread.sleep(120000);//give cassandra enough time to build the index.
client.insert(ByteBuffer.wrap("bsanderson".getBytes()), columnParent, column, ConsistencyLevel.ONE);
IndexClause indexClause = new IndexClause();
indexClause.start_key = ByteBuffer.allocate(0);
IndexExpression indexExpression = new IndexExpression();
indexExpression.column_name = ByteBuffer.wrap(STATE.getBytes());
indexExpression.value = ByteBuffer.wrap("UT".getBytes());
indexExpression.op = IndexOperator.EQ;
indexClause.addToExpressions(indexExpression);
SliceRange sliceRange = new SliceRange();
sliceRange.count = 10;
sliceRange.start = ByteBuffer.allocate(0);
sliceRange.finish = ByteBuffer.allocate(0);
sliceRange.reversed = false;
SlicePredicate slicePredicate = new SlicePredicate();
slicePredicate.slice_range = sliceRange;
List<KeySlice> keys = client.get_indexed_slices(columnParent, indexClause, slicePredicate, ConsistencyLevel.ONE);
if (!keys.isEmpty()) {
System.out.println("expecting: bsanderson htayler");
System.out.print("actual: ");
for (KeySlice key : keys) {
System.out.print(new String(key.getKey()) + " ");
}
} else {
System.out.println("failed to find indexed item");
}
} catch (Exception ex) {
Logger.getLogger(IndexLaterTest.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
client.system_drop_keyspace(KEYSPACE_NAME);
} catch (Exception ex) {
Logger.getLogger(IndexLaterTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
} finally {
transport.close();
}
}
The results are :-
expecting: bsanderson htayler
actual: bsanderson
回答1:
For the purpose of record. The problem lies in the following code.
ColumnDef columnDef1 = new ColumnDef(ByteBuffer.wrap(BIRTH_DATE.getBytes()), "LongType");
columnDef1.index_type = IndexType.KEYS;
Defining the index_type alone is not enough. You need to set a index_name as well for it to work.
回答2:
I does take some time for the index to be built. It should take less than a second in this case, but it might not have completed by the time you make the query.
Try sleeping for one or two seconds after creating the index and see if that changes the results.
来源:https://stackoverflow.com/questions/4677057/how-to-programatically-add-index-to-cassandra-0-7