2

次の Cassandra スキーマがあります。

ColumnFamily: FloatArrays {
    SCKey: SuperColumn Key (Integer) {
        Key: FloatArray (float[]) {
            field (String): value (String)
        }
    }
}

このスキーマに準拠するデータを挿入するために、Hector で次のテンプレートを作成しました。

template = new ThriftSuperCfTemplate<Integer, FloatArray, String>(
    keyspace, "FloatArrays", IntegerSerializer.get(),
    FloatArraySerializer.get(), StringSerializer.get());

カスタム シリアライザーを作成 (および単体テスト) した FloatArray を (デ) シリアル化するには、次のようにします。

public class FloatArraySerializer extends AbstractSerializer<FloatArray> {

    private static final FloatArraySerializer instance = 
        new FloatArraySerializer();

    public static FloatArraySerializer get() {
        return instance;
    }

    @Override
    public FloatArray fromByteBuffer(ByteBuffer buffer) {
        buffer.rewind();
        FloatBuffer floatBuf = buffer.asFloatBuffer();
        float[] floats = new float[floatBuf.limit()];
        if (floatBuf.hasArray()) {
            floats = floatBuf.array(); 
        } else {
            floatBuf.get(floats, 0, floatBuf.limit());
        }
        return new FloatArray(floats);
    }

    @Override
    public ByteBuffer toByteBuffer(FloatArray theArray) {
        float[] floats = theArray.getFloats();
        ByteBuffer byteBuf = ByteBuffer.allocate(4 * descriptor.length);
        FloatBuffer floatBuf = byteBuf.asFloatBuffer();
        floatBuf.put(floats);
        byteBuf.rewind();
        return byteBuf;
    }

}

ここで、ややこしい部分があります。float の配列を格納してから取得しても、同じ結果は返されません。実際、配列内の要素の数は同じではありません。結果を取得するために使用するコードを以下に示します。

SuperCfResult<Integer, FloatArray, String> result = 
    template.querySuperColumns(hash);
for (FloatArray floatArray: result.getSuperColumns()) {
    // Do something with the FloatArrays
}

私は Cassandra/Hector にまったく慣れていないので、ここで概念的な間違いを犯していますか? 今のところ、どこが間違っているのか手がかりさえありません。シリアライザーは問題ないようです。検索を続けるためのヒントを教えてください。どうもありがとう!

4

2 に答える 2

1

あなたは正しい方向に進んでいると思います。ByteBufferを使用するとき、次のステートメントが必要になることがあります。

import org.apache.thrift.TBaseHelper;

       ... 

ByteBuffer aCorrectedByteBuffer = TBaseHelper.rightSize(theByteBufferIWasGiven);

バイトバッファの値がオフセットとしてバッファに格納されることがありますが、Serializersは、バイトバッファの値がオフセット0から始まると想定しているようです。TBaseHelperは、Serializer実装の前提条件が有効になるように、オフセットを可能な限り修正します。 。

配列入力と配列出力の長さの違いは、間違ったオフセットで開始した結果です。シリアル化された値の最初の1バイトまたは2バイトには、配列の長さが含まれます。

于 2012-07-03T20:53:21.173 に答える
0

クリスのおかげで私は問題を解決しました。シリアライザーは次のようになります。

public class FloatArraySerializer extends AbstractSerializer<FloatArray> {

    private static final FloatArraySerializer instance = 
        new FloatArraySerializer();

    public static FloatArraySerializer get() {
        return instance;
    }

    @Override
    public FloatArray fromByteBuffer(ByteBuffer buffer) {
        ByteBuffer rightBuffer = TBaseHelper.rightSize(buffer);  // This does the trick
        FloatBuffer floatBuf = rightBuffer.asFloatBuffer();
        float[] floats = new float[floatBuf.limit()];
        if (floatBuf.hasArray()) {
            floats = floatBuf.array(); 
        } else {
            floatBuf.get(floats, 0, floatBuf.limit());
        }
        return new FloatArray(floats);
    }

    @Override
    public ByteBuffer toByteBuffer(FloatArray theArray) {
        float[] floats = theArray.getDescriptor();
        ByteBuffer byteBuf = ByteBuffer.allocate(4 * descriptor.length);
        FloatBuffer floatBuf = byteBuf.asFloatBuffer();
        floatBuf.put(floats);
        byteBuf.rewind();
        return byteBuf;
    }

}
于 2012-07-04T06:40:49.420 に答える