2012-01-17 4 views
2

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

ответ

2

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); 

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

+0

я попытаюсь это но я на самом деле не использую cql, скорее я просто получаю список и получаю элемент столбца из этого списка. Теперь предположим, что у меня есть Column.name = Year, это может быть длинный или UTF-8 или любой другое значение. Мне нужно знать фактический тип, чтобы я мог принять правильный метод для преобразования ByteBuffer в long или String. –

5

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

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

Используя API-интерфейс Hector, ниже перечислены все семейства столбцов в пространстве ключей и подробная информация о имени 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.

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

E.g. без Hector метод, который я использовал, чтобы сделать это выглядит как

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() 
+0

Как получить тип динамического столбца? – Transcendence

+0

Вы имеете в виду столбец с классом проверки ** DynamicComposite **? Если это так, это все равно похоже; AbstractType <- AbstractCompositeType <- CompsiteType и DynamicCompositeType. Затем получите список Компараторов из CompositeType. – libjack

0

Обычно Я знаю, какие типы данных ожидать в моем приложении, особенно если я использую static column families; но если я использую динамические семейства столбцов, или если я просто хочу сохранить свой общий код, я склоняю свои столбцы к 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; 
} 
Смежные вопросы