libQtCassandra sorts the results in its QMap

As I was working with libQtCassandra for the Snap! project, I notices a problem in one of my queries. That's actually the only one where I used the reverse flag. This flag is used to ask Cassandra to return its data in reverse order. That works perfectly, on Cassandra's side, but not so well in libQtCassandra...

In order to allow the C++ array operator (i.e. the square brackets ([]) are overloaded!) in the libQtCassandra, I decided to make use of QMap to be able to quickly access the data. This means you can create a Cassandra context and then access data like this:

value = context["table-name"]["row-name"]["cell-name"];

As we can see, to find the cell (called a column in Cassandra's language) by name, the fastest is to have a QMap of the data cached in memory.

This is great, only once in a while you may be interested in having a specific order in Cassandra and get the data out in that order (the reverse order being once of those!) Right now this is not possible with libQtCassandra unless you read cells one by one (which is going to be slow!)

For the reverse effect, though, there is an easy solution: you can read your results in reverse order. The row gives you direct access to the QMap (see the cells() function) and with a copy of that map you can use the following code to handle the data in reverse order:

    QtCassandra::QCassandra::pointer_t cassandra(QtCassandra::QCassandra::create());
    QtCassandra::QCassandraContext::pointer_t context(cassandra->findContext(context_name));
    QtCassandra::QCassandraTable::pointer_t table(context->findTable(table_name));
    QtCassandra::QCassandraRow::pointer_t row(table->row(row_name));
    QtCassandra::QCassandraColumnRangePredicate column_predicate;
    column_predicate.setCount(100); // 100 is the default, put 5 if you need 5
    column_predicate.setIndex(); // behave like an index
    column_predicate.setStartColumnName(end_key); // start/end keys are reversed
    column_predicate.setEndColumnName(start_key);
    column_predicate.setReversed(); // read the last first
    for(;;)
    {
        row->clearCache();
        row->readCells(column_predicate);
        QtCassandra::QCassandraCells const cells(row->cells());
        if(cells.isEmpty())
        {
            // end of the row reached
            break;
        }
        // handle one batch
        QMapIterator<QByteArray, QtCassandra::QCassandraCell::pointer_t> c(cells);
        c.toBack(); // go to c.end()
        while(c.hasPrevious())
        {
            c.previous(); // do a --c
            QtCassandra::QCassandraCell::pointer_t cell(c.value());
            [...your handling of that data...]
        }
    }

I underlined the few important lines of code.

Note that, at this point, the only sort supported by libQtCassandra is a binary sort. It compares bytes as unsigned char, that's all.

In a later version we will offer a list of cells in the order loaded, i.e. using a QVector.

Snap! Websites
An Open Source CMS System in C++

Contact Us Directly