2013-10-15 137 views
0

我一直在使用Cassandra的DB 2.0.1(CQL 3)解压卡桑德拉地图类型

CREATE TABLE fans (id text PRIMARY KEY, fans map<text, text>); 
INSERT INTO fans (id, fans) VALUES ('John', {'fruit' : 'apple', 'band' : 'Beatles'}); 
UPDATE fans SET fans = fans + {'movie' : 'Cassablanca'} WHERE id = 'John'; 

它工作的优良创建了一些数据。

cqlsh:testdb> SELECT * FROM fans; 

id | fans 
------+--------------------------------------------------------------- 
John | {'band': 'Beatles', 'fruit': 'apple', 'movie': 'Cassablanca'} 

(1 rows) 

现在我试图用PHP(thobbs/phpcassa v1.1.0)获取数据。

include_once ("/include/autoload.php"); 
$pool = new phpcassa\Connection\ConnectionPool('testdb'); 
$connection = $pool->get(); 
$rows = $connection->client->execute_cql3_query("SELECT id, fans FROM fans", cassandra\Compression::NONE, cassandra\ConsistencyLevel::ONE); 
var_dump($rows->rows); 
$pool->return_connection($connection); 
unset($connection); 
$pool->close(); 

它也工作正常。

array (size=1) 
    0 => 
    object(cassandra\CqlRow)[10] 
     public 'key' => string '' (length=0) 
     public 'columns' => 
     array (size=2) 
      0 => 
      object(cassandra\Column)[11] 
       public 'name' => string 'id' (length=2) 
       public 'value' => string 'John' (length=4) 
       public 'timestamp' => null 
       public 'ttl' => null 
      1 => 
      object(cassandra\Column)[12] 
       public 'name' => string 'fans' (length=4) 
       public 'value' => string '��band�Beatles�fruit�apple�movie�Cassablanca' (length=51) 
       public 'timestamp' => null 
       public 'ttl' => null 

的问题是如何打开该表示为图中的值? 我可以看到

��band�Beatles�fruit�apple�movie�Cassablanca 

,我知道这是showld

{'band': 'Beatles', 'fruit': 'apple', 'movie': 'Cassablanca'} 

是否有任何内部功能反序列化或解包编码字符串转换成地图或数组?

我wroute一个功能读取不可打印符号:

function unistr_to_ords($str, $encoding = 'UTF-8') { 
    $str = mb_convert_encoding($str, 'UCS-4BE', $encoding); 
    $ords = array(); 
    for ($i = 0; $i < mb_strlen($str, 'UCS-4BE'); $i++) { 
     $s2 = mb_substr($str, $i, 1, 'UCS-4BE'); 
     $val = unpack('N', $s2); 
     $ords[] = $val[1]; 
    } 
    return($ords); 
} 

当我尝试将其与值I看到以下结果:

array (size=51) 
    0 => int 0 
    1 => int 3 
    2 => int 0 
    3 => int 4 
    4 => int 98 
    5 => int 97 
    6 => int 110 
    7 => int 100 
    8 => int 0 
    9 => int 7 
    10 => int 66 
    11 => int 101 
    12 => int 97 
    13 => int 116 
    14 => int 108 
    15 => int 101 
    16 => int 115 
    17 => int 0 
    18 => int 5 
    19 => int 102 
    20 => int 114 
    21 => int 117 
    22 => int 105 
    23 => int 116 
    24 => int 0 
    25 => int 5 
    26 => int 97 
    27 => int 112 
    28 => int 112 
    29 => int 108 
    30 => int 101 
    31 => int 0 
    32 => int 5 
    33 => int 109 
    34 => int 111 
    35 => int 118 
    36 => int 105 
    37 => int 101 
    38 => int 0 
    39 => int 11 
    40 => int 67 
    41 => int 97 
    42 => int 115 
    43 => int 115 
    44 => int 97 
    45 => int 98 
    46 => int 108 
    47 => int 97 
    48 => int 110 
    49 => int 99 
    50 => int 97 

正如我理解0(零)是一个分离器,在0之后是一个长度,例如第一个03表示地图中的3个项目。那么04意味着4是单词'band'的长度,那么07意味着单词'Beatles'的长度为7的新单词等等。

但是是否有任何内部提取地图,列表或集的内置方法或函数?

回答

1

有人可能已经破解了一些东西,但现在官方的回答是,phpcassa不支持CQL3,因此不支持列集合(地图,集合和列表)等CQL3专用功能。

0

我一直希望能找到一些能够做到这一点的东西,但是不能这样我就砍掉了这个。适用于<文本,文本>的地图。这是我正在使用的。以为我会把它放在这里,以供其他人看。

function cql3_map_to_array($map) { 
    $byte_array = unpack('C*', $map); 
    $map_array = array(); 

    if(sizeof($byte_array) > 2) { 
     $pos = 1; 
     $size = (intval($byte_array[$pos]) * 256) + intval($byte_array[$pos + 1]); 
     $pos += 2; 

     while($size > 0) { 
      $length = (intval($byte_array[$pos]) * 256) + intval($byte_array[$pos + 1]); 
      $pos += 2; 
      $key = substr($map, $pos - 1, $length); 
      $pos += $length; 

      $length = (intval($byte_array[$pos]) * 256) + intval($byte_array[$pos + 1]); 
      $pos += 2; 
      $value = substr($map, $pos - 1, $length); 
      $pos += $length; 

      $map_array[$key] = $value; 

      $size--; 
     } 
    } 

    return $map_array; 
}