부분 복합 열에 대한 범위 쿼리
문제
Astyanax를 사용하여 필요한 모든 범위 쿼리를 만드는 방법을 알 수 없습니다.설명된 내용을 시도해 보았습니다. 여기 하지만 작동하지 않는 것 같습니다.
참고로 저는 이 모든 것이 잘 작동하는 Hector 세계에서 왔으며 설명할 수 없는 이유로 Astyanax로 전환하기로 결정했습니다.
다음과 같이 설명된 컬럼 패밀리가 있습니다.최신 TimeUUID를 먼저 가질 수 있는 "ReversedType"을 참고하세요.나머지 부분에는 영향을 주어서는 안 됩니다. 적어도 Hector에게는 영향을 미치지 않았습니다.
ColumnFamily: mycf
Key Validation Class: org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.UTF8Type)
Default column value validator: org.apache.cassandra.db.marshal.UTF8Type
Columns sorted by: org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.ReversedType(org.apache.cassandra.db.marshal.TimeUUIDType))
Astyanax CF의 정의는 다음과 같습니다.
public static final CF = new ColumnFamily<Rowkey, Column>(
NAME,
new AnnotatedCompositeSerializer<Rowkey>(Rowkey.class),
new AnnotatedCompositeSerializer<Column>(Column.class),
StringSerializer.get()
);
public static class Column {
@Component(ordinal = 0)
public String colname = null;
@Component(ordinal = 1)
public UUID timeUUID = null;
}
public static class Rowkey {
@Component(ordinal = 0)
public String aid;
@Component(ordinal = 1)
public String cid;
}
설명된 대로 부분 복합을 사용하여 쿼리를 수행할 수 있었습니다. 여기.나에게 정말로 필요한 것은 다음과 같은 범위 쿼리를 수행할 수 있는 것입니다.
# Range 1
# Should get the 10 first elements of the rowkey
colstart: null
colend: null
limit: 10
# Range 2
# Should get the 10 first elements of the rowkey
# that has as first part of the composite the string "mycol"
colstart: Column("mycol", null)
colend: Column("mycol", null)
limit: 10
# Range 3
# Should get the 10 first elements of the rowkey
# that has as first part of the composite the string "mycol"
# and with a timeuuid created with a timstamp between 'timestampStart' and 'timestampEnd'
colstart: Column("mycol", TimeUUID(timestampStart))
colend: Column("mycol", TimeUUID(timestampEnd))
limit: 10
# Range 4, not actually a range
# Should get the 1 column composed of "mycol" and existingTimeUUID
colstart: Column("mycol", existingTimeUUID)
colend: Column("mycol", existingTimeUUID)
limit: 10
제가 시도한 3가지 방법은 다음과 같습니다.
# Code 1
keyspace.prepareQuery(columnFamily)
.getKey(rowkey)
.withColumnRange(columnStart, columnEnd, false, 10)
.execute()
.getResult();
# Code 2
RangeBuilder rangeBuilder = new RangeBuilder()
.setStart(columnStart, CF.getColumnSerializer())
.setEnd(columnEnd, CF.getColumnSerializer())
.setReversed(false)
.setLimit(10);
keyspace.prepareQuery(columnFamily)
.getKey(rowkey)
.withColumnRange(rangeBuilder.build())
.execute()
.getResult();
# Code 3
CompositeRangeBuilder rangeBuilder = ((AnnotatedCompositeSerializer<Column>) colSerializer)
.buildRange()
.withPrefix(columnStart.colname)
.greaterThanEquals(columnStart.timeUUID)
.lessThanEquals(columnEnd.timeUUID)
.limit(10);
keyspace.prepareQuery(columnFamily)
.getKey(rowkey)
.withColumnRange(rangeBuilder.build())
.execute()
.getResult();
내 Hector 배경에 따르면 내가 제공하는 합성(주석이 달린 클래스)에는 EQUALITY 매개변수가 누락되었습니다.Code 3
접두사는 시작과 끝 모두에 적용되므로 필요한 작업을 정확히 수행하지 않으며 예를 들어 (col1, timUUID1)에서 (col2, TimeUUID2)까지 쿼리 범위를 지정하려는 경우 접두사가 다를 수 있습니다.
나는 성공했다 Range 4
세 가지 코드를 모두 쉽게 사용할 수 있습니다.
나는 성공했다 Range 1
이렇게 하면 세 가지 코드를 모두 사용하여 작업할 수 있습니다.
- ~ 안에
Code 1
나는 시작과 끝의 매개변수로 null을 주었다 - ~ 안에
Code 2
나는 setStart 및 setEnd 호출을 피했습니다. - ~ 안에
Code 3
나는 Prefix나 동등 메서드를 사용하여 호출하는 것을 피했습니다.
나는 성공했다 Range 2
오직 와 함께 일하다 Code 3
:
- 나는 둘 중 하나를 제공했다
greaterThanEquals(columnStart.colname)
또는lessThanEquals(columnStart.colname)
다른 동등/접두사 방법은 없습니다.
나는 만들지 못했다. Range 3
조금도.
분명히, 나는 단지 사용하고 싶습니다 Code 1
나는 실제로 쿼리할 컬럼 패밀리를 모르기 때문에.여기서는 복합 열이 포함된 예를 사용하고 있지만 복합 열이 아니거나 필드가 2개 이상일 수 있습니다.
hector에서는 정말 이것만큼 쉬우며 이에 상응하는 것을 원합니다:
MultigetSliceQuery<K, C, V> q = HFactory.createMultigetSliceQuery(connection.getKeyspace(), this.getRowKeySerializer(), this.getColumnNameSerializer(), this.getColumnValueSerializer());
q.setColumnFamily(this.getCfName());
q.setKeys(keys)
q.setRange(colStart, colEnd, reversed, count);
q.execute();
모든 유형의 colStart 및 colEnd를 사용하고 복합인 경우 각 구성 요소에 정의된 Equality를 사용하여 부분 복합을 허용합니다.
당신의 도움을 주셔서 감사합니다.
해결책
위의 방법을 사용하여 원하는 모든 작업을 수행할 수 없었지만 마음에 들지 않더라도 작동하는 네 번째 방법을 찾았습니다.
나는 ByteBuffer
버전 withColumnRange
~에 Code 1
.시작 및 끝 버퍼는 다음과 같이 실제 Composite 클래스를 사용하여 구축됩니다.
public static <T> ByteBuffer toRangeStart(List<Object> list, boolean reversed) {
return toRangeValue(list, reversed ? ComponentEquality.GREATER_THAN_EQUAL : ComponentEquality.EQUAL);
}
public static <T> ByteBuffer toRangeEnd(List<Object> list, boolean reversed) {
return toRangeValue(list, reversed ? ComponentEquality.EQUAL : ComponentEquality.GREATER_THAN_EQUAL);
}
public static <T> ByteBuffer toRangeValue(List<Object> list, ComponentEquality eq) {
// We use a real composite as we didn't find any other way to build those ranges
Composite c = new Composite();
int i;
for (i = 0; i < list.size() - 1; i++) {
c.addComponent(list.get(i), SerializerTypeInferer.getSerializer(list.get(i)), ComponentEquality.EQUAL);
}
c.addComponent(list.get(i), SerializerTypeInferer.getSerializer(list.get(i)), eq);
return c.serialize();
}