IK.AM

@making's tech note


Cassandra0.7.0のSecondary indexesを使用したJava APIサンプル

🗃 {Middleware/NoSQL/Cassandra}
🗓 Updated at 2011-01-13T19:15:15Z  🗓 Created at 2011-01-13T19:15:15Z   🌎 English Page

ここと同じモデルを使います。

get users where birth_date > 1000 and blood = 'A'相当の処理をJavaで実装します。

セカンダリインデックスによるカラム値の範囲検索にはget_indexed_slicesメソッドを使います。get_range_slicesとよく似ています。(実際にこのページのMain4をコピペしました。)

CLIでまず試す

[default@demo] get users where birth_date > 1000 and blood = 'A';
-------------------
RowKey: xxx
=> (column=birth_date, value=1999, timestamp=1294946222506)
=> (column=blood, value=A, timestamp=1294946222506)
=> (column=full_name, value=Taro Yamada, timestamp=1294946222506)
-------------------
RowKey: hoge
=> (column=birth_date, value=2000, timestamp=1294945329023)
=> (column=blood, value=A, timestamp=1294945329023)
=> (column=full_name, value=Hogeo Hoge, timestamp=1294945329023)

2 Rows Returned.

Javaで実装

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;

import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.IndexClause;
import org.apache.cassandra.thrift.IndexExpression;
import org.apache.cassandra.thrift.IndexOperator;
import org.apache.cassandra.thrift.KeySlice;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

public class SecondaryIndexSample1 {
    public static final String CHARSET = "UTF-8";

    public static void main(String[] args) throws Exception {
        TTransport transport = new TSocket("localhost", 9160);
        TFramedTransport tf = new TFramedTransport(transport);
        TProtocol proto = new TBinaryProtocol(tf);
        Cassandra.Client client = new Cassandra.Client(proto);

        transport.open();

        try {
            // キースペース名
            String ksName = "demo";
            // カラムファミリ名
            String cfName = "users";

            client.set_keyspace(ksName);

            SlicePredicate predicate = new SlicePredicate();
            predicate.setColumn_names(Arrays.asList(buffer("full_name"),
                    buffer("blood")));

            ColumnParent parent = new ColumnParent(cfName);

            // get users where birth_date > 2000 and blood = 'A' 相当
            IndexClause clause = new IndexClause();
            clause.setStart_key(new byte[0]);
            clause.setExpressions(Arrays.asList(
                    new IndexExpression(buffer("birth_date"), IndexOperator.GT,
                            FBUtilities.toByteBuffer(1000L)),
                    new IndexExpression(buffer("blood"), IndexOperator.EQ,
                            buffer("A"))));

            List<KeySlice> results = client.get_indexed_slices(parent, clause,
                    predicate, ConsistencyLevel.ONE);

            System.out.println("----------");
            for (KeySlice keySlice : results) {
                List<ColumnOrSuperColumn> coscs = keySlice.getColumns();
                for (ColumnOrSuperColumn cosc : coscs) {
                    Column column = cosc.getColumn();
                    System.out.printf("%s=%s%n", new String(column.getName(),
                            CHARSET), new String(column.getValue(), CHARSET));
                }
                System.out.println("----------");

            }
        } finally {
            transport.close();
        }
    }

    public static ByteBuffer buffer(String value)
            throws UnsupportedEncodingException {
        return ByteBuffer.wrap(value.getBytes(CHARSET));
    }
}

実行結果

----------
blood=A
full_name=Taro Yamada
----------
blood=A
full_name=Hogeo Hoge
----------

0.7.0では範囲検索する場合、他のセカンダリインデックスをもつカラム値を指定しないといけないことに注意(birth_date > 1000だけだはエラーになる。)


✒️️ Edit  ⏰ History  🗑 Delete