как получить тип значения столбца - PullRequest
2 голосов
/ 17 января 2012

Я использую Java для подключения к Cassandra. Я хочу сделать что-то вроде проверки типа данных столбца, т.е. является ли он длинным или UTF-8, потому что, если он длинный, тогда я могу получить значение как column.value.getLong () , но если это UTF-8 или другой, я должен преобразовать ByteBuffer в Строка. Может кто-нибудь помочь мне, как я могу найти тип столбца?

Ответы [ 3 ]

5 голосов
/ 19 января 2012

Чтобы получить информацию, специфичную для столбца, сначала вам нужно будет выполнить итерацию по определениям семейства столбцов в определении Keyspace и сопоставить семейство столбцов по имени - можно использовать Thrift API, но я бы предложил использовать Hector.

С помощью определения семейства столбцов выполните итерацию метаданных столбца и найдите соответствие для нужного столбца. Затем обратитесь к соответствующему определению столбца, чтобы получить класс проверки. Если метаданные отсутствуют или соответствующий столбец отсутствует, класс проверки будет классом проверки по умолчанию в определении семейства столбцов.

Используя Hector API, ниже приведен список всех семейств столбцов в пространстве ключей и полные сведения об имени CF, переданном в качестве аргумента.

public static void main(String[] args) {
    String hostPort = "localhost:9160";
    String cfname = null;

    if (args.length < 1)
    {
        System.out.println("Expecting <CF>  as arguments");
        System.exit(1);
    }
    cfname = args[0];

    Cluster cluster = HFactory.getOrCreateCluster( "myCluster", hostPort );
    KeyspaceDefinition ksdef = cluster.describeKeyspace("myKeyspace");

    for (ColumnFamilyDefinition cfdef: ksdef.getCfDefs()) {
        System.out.println(cfdef.getName());
        if (cfdef.getName().equals(cfname)) {
            System.out.println("Comment: " + cfdef.getComment());
            System.out.println("Key: " + cfdef.getKeyValidationClass());
            System.out.println("Comparator: " + cfdef.getComparatorType().getTypeName());
            System.out.println("Default Validation:" + cfdef.getDefaultValidationClass());
            System.out.println("Column MetaData:");
            for (ColumnDefinition cdef: cfdef.getColumnMetadata()) {
                System.out.println("  Column Name: " + Charset.defaultCharset().decode(cdef.getName()).toString());
                System.out.println("    Validation Class: " + cdef.getValidationClass());
                System.out.println("    Index Name: " + cdef.getIndexName());
                System.out.println("    Index Type: " + cdef.getIndexType().toString());
            }
        }
    }


}

Если вы запустите это, вы заметите, что любой класс проверки будет принадлежать пакету org.apache.cassandra.db.marshal, и каждый тип является производным от AbstractType.

Когда у вас есть Тип, вы можете принимать решения по вашим данным. Например, если вы пишете инструмент для создания дампа данных, вам может потребоваться получить строковое представление каждого столбца, и вы можете использовать AbstractType для получения строкового представления значения, используя TypeParser для создания типа.

например. не-Гектор метод, который я использовал для этого, выглядит как

private String getAsString(java.nio.ByteBuffer bytes, String marshalType) {

    String val = null;
    try {
        AbstractType abstractType = TypeParser.parse(marshalType);
        val = abstractType.getString(bytes);
    } catch (ConfigurationException e) {
        e.printStackTrace();
    }

    return val;
}

Вы можете использовать этот метод для вывода ключей и имен столбцов; эти имена типов также включены в определение семейства столбцов.

Один быстрый ярлык, если вы знаете, что значение столбца является строкой, поскольку в байтовом буфере нет метода getString, вы должны использовать java.nio.charset.Charset:

Charset.defaultCharset().decode(col.getValue()).toString()
2 голосов
/ 18 января 2012

https://issues.apache.org/jira/browse/CASSANDRA-2302 - это запрос функции Cassandra для реализации ResultSet.getMetaData. Комментарий содержит информацию о том, как к нему можно получить доступ:

ResultSet rs = stmt.executeQuery("select ...");
ResultSetMetaData md = rs.getMetaData();
CassandraResultSetMetaData cmd = md.unwrap(CassandraResultSetMetaData.class);

Однако, я боюсь, что это не было реализовано до Cassandra 0.8. Ваш вопрос помечен cassandra-0.7.

0 голосов
/ 11 октября 2013

Обычно я знаю, какие типы данных следует ожидать в моем приложении, особенно если я использую семейства статических столбцов ; но если я использую динамические семейства столбцов или просто хочу, чтобы мой код был универсальным, я склонен устанавливать для своих столбцов значение BytesType и сериализовывать / десериализовывать их как Object типы.

например. рассмотрим следующее семейство столбцов:

create column family album
  with key_validation_class = 'UTF8Type'
  and comparator = 'UTF8Type'
  and default_validation_class = 'BytesType';

Используя ObjectSerializer Гектора, вы можете читать и записывать значения столбцов в виде Object типов. Значения фактически будут сериализованными объектами в вашем семействе столбцов, а после десериализации в коде Java эти значения станут пригодными для использования объектами Java. Вот как будет выглядеть мой клиентский код:

/* some code left out for brevity */

String columnFamily = "album";
ThriftColumnFamilyTemplate<String, String> template;

public void write(String key, Map<String, ?> album)
  Mutator<String> mutator = template.createMutator();

  for (Entry<String, ?> entry : album.entrySet()) {
    mutator.addInsertion(key, columnFamily, HFactory.createColumn(entry.getKey(),
        entry.getValue(), StringSerializer.get(), ObjectSerializer.get()));
  }
  mutator.execute();
}

public Map<String, ?> read(String key) {
  ColumnFamilyResult<String, String> result = template.queryColumns(key);

  Map<String, Object> album = new HashMap<String, Object>();
  for (String name : result.getColumnNames()) {
    HColumn<String, ByteBuffer> column = result.getColumn(name);
    album.put(name, ObjectSerializer.get().fromByteBuffer(column.getValue()));
  }
}

Вот простой тест, показывающий, что значения столбцов сохраняют свои типы Object после десериализации из семейства столбцов:

public static void main(String[] args) {
  Map<String, Object> album = new HashMap<String, Object>();
  album.put("name", "Up The Bracket");
  album.put("release", 2002);
  album.put("in_stock", true);

  /* write into column family and read it back out */
  client.write("up_the_bracket", album);
  Map<String, ?> result = client.read("up_the_bracket");

  /* the column values are deserialized back into their original types */
  assert result.get("name") instanceof String;
  assert result.get("release") instanceof Integer;
  assert result.get("in_stock") instanceof Boolean;
}
...