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

我知道它应该是

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

是否有任何内部函数可以将编码字符串反序列化或解压缩到映射或数组中?

我编写了一个读取不可打印符号的函数:

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

当我尝试使用该值时,我看到以下结果:

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 的新单词,依此类推。

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

4

2 回答 2

1

可能有人一起破解了一些东西,但目前官方的回答是 phpcassa 不支持 CQL3,因此不支持仅 CQL3 的功能,如列集合(映射、集合和列表)。

于 2013-10-16T22:09:13.837 回答
0

我希望能找到一些东西来做这件事,但我做不到,所以我把它破解了。适用于 <text,text> 的地图。这就是我正在使用的。以为我会把它放在这里给其他人看。

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;
}
于 2014-06-12T17:58:55.460 回答