Распакуйте карту типа Cassandra
Я создал некоторые данные, используя 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 означает новое слово с длиной 7 для слова 'Beatles' и так далее.
Но есть ли какой-либо внутренний встроенный метод или функция для извлечения карты, списка или набора?
2 ответа
Кто-то, возможно, что-то взломал вместе, но сейчас официальный ответ таков: phpcassa не поддерживает CQL3 и, следовательно, не поддерживает функции только для CQL3, такие как коллекции столбцов (карты, наборы и списки).
Я надеялся найти что-нибудь для этого, но не смог, так что взломал это. Работает для карты <текст, текст>. Что я и использую. Думаю, я надену это здесь для всех, кто ищет.
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;
}