Запрос диапазона для частичных составных столбцов

StackOverflow https://stackoverflow.com//questions/21042063

  •  21-12-2019
  •  | 
  •  

Вопрос

Я не могу понять, как выполнить все запросы диапазона, которые мне нужны, используя Astyanax.Я попробовал то, что было объяснено здесь но, похоже, это не работает.

К вашему сведению, я родом из мира Hector, где у меня все это прекрасно работает, и по причинам, которые я не буду объяснять, мы решили перейти на Astyanax.

У меня есть семейство столбцов, описанное следующим образом.Обратите внимание на "ReversedType", который позволяет нам сначала получить последний TimeUUID.Это не должно повлиять на остальное, по крайней мере, с Гектором этого никогда не происходило:

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, в составном файле, который я даю (аннотированные классы), отсутствует параметр РАВЕНСТВА.Code 3 не стал бы делать именно то, что мне нужно, поскольку префикс применяется как к началу, так и к концу, и они могут отличаться, если бы я хотел, например, варьировать запрос от (col1, timUUID1) до (col2, TimeUUID2).

Мне удалось сделать Range 4 легко работайте со всеми тремя кодами.

Мне удалось сделать Range 1 работайте со всеми тремя кодами, поступая следующим образом:

  • В Code 1 я дал null в качестве параметра для начала и конца
  • В Code 2 я избегал вызывать setStart и setEnd
  • В Code 3 я избегал вызова withPrefix или любого другого метода равенства.

Мне удалось сделать 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 любого типа и if composite, что позволяет создавать частичные композиции с равенством, определенным для каждого компонента.

Спасибо за вашу помощь.

Это было полезно?

Решение

Я не смог сделать все, что хотел, используя вышеперечисленные методы, но я нашел 4-й, который, хотя мне и не нравится, работает.

Я использую ByteBuffer версия withColumnRange в Code 1.Начальный и конечный буферы создаются с использованием фактического составного класса следующим образом:

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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top