Skip to content

Zeroplex 生活隨筆

軟體開發、伺服器和生活瑣事

小 縮小字型大小。 中 重設字型大小。 大 放大字型大小。

標籤: Cassandra

使用 datastax/php-driver 對 Cassandra 做 query 需要留意的地方

Posted on 2017 年 9 月 12 日2021 年 3 月 12 日 By 日落 在〈使用 datastax/php-driver 對 Cassandra 做 query 需要留意的地方〉中尚無留言

最近在研究如何把 log 塞到 Cassandra 中,使用的 Datastax 的 php-driver 輕鬆很多,但還是有一些需要留意的地方,免得莫名其妙鬼打牆。

這邊先假設我要記錄一個使用者上傳檔案的記錄,包含 ID、檔案名稱、檔案大小以及上傳日期,建立了一個 table:

CREATE TABLE hermes_log.file (
    id uuid,
    name text,
    size decimal,
    create_time timestamp,
    PRIMARY KEY (id, name, size, create_time)
)

這個時候使用 PHP 塞資料進入,直接建立 CQL 且不使用 prepare/binding,可以成功執行 insertion:

<?php

$cluster = Cassandra::cluster()->build();
$session = $cluster->connect();
$cql = "
    insert into hermes_log.file
    (
        id,
        name,
        size,
        create_time
    ) values (
        uuid(),
        'gavatar.jpg',
        123.4,
        '2017-01-01 10:30:45.678'
    )
";

$session->execute($cql);

cqlsh 看一下資料格式:

cqlsh:zero_test> select name, size, create_time from file;

 name        | size  | create_time
-------------+-------+---------------------------------
 gavatar.jpg | 123.4 | 2017-01-01 02:30:45.678000+0000

(1 rows)

除了日期會自動轉為 UTC+00:00 以外其他都沒什麼太大的問題。


接下來把 PHP 改為 prepare/bind 格式:

$cql = "
    insert into hermes_log.file
    (
        id,
        name,
        size,
        create_time
    ) values (
        uuid(),
        ?,
        ?,
        ?
    )
";

$session->execute($cql, [
    'gavatar.jpg',
    123.4,
    '2017-01-01 10:30:45.678'
]);

執行的時候你會看到錯誤訊:「Uncaught CassandraExceptionInvalidQueryException: Invalid amount of bind variables in your.php」,意思是找不到可以 binding 的資料。仔細去翻文件才會注意到 binding 的資料,不是直接放進 array 就好,而是要放在 key「arguments」底下,所以至卻的寫法應該是:

$session->execute($cql, [
    'arguments' => [
        'gavatar.jpg',
        123.4,
        '2017-01-01 10:30:45.678'
    ],
]);

再次執行後,錯誤訊息不一樣了「Uncaught CassandraExceptionInvalidQueryException: Expected 8 or 0 byte long for date (23) ….」,看起來 create_time 這邊沒辦法使用字串來代表新增日期。

如果你有注意到 Cassandra 是使用 Java 實作的,應該不難理解 PHP 和 Java 的資料型態差異很大,因此 DataStax 的 php-driver library 為了讓資料傳遞時不會發生問題,寫了不少 adapter 來解決資料型態的相容問題,像是 CassandraTimestamp、CassandraDecimal 等,這些類別可以在文件中的 Cassandra namespace 中找到。

所以按照規格改好以後,應該會是下面這樣:


$createTime = microtime(true);
list($sec, $ms) = explode('.', $createTime);
$sec = intval($sec);
$ms = intval(($createTime - $sec) * 1000000); // 毫秒取六位數

$session->execute($cql, [
    'arguments' => [
        'gavatar.jpg',
        new CassandraDecimal(strval(123.4)),
        new CassandraTimestamp($sec, $ms),
    ],
]);
Tags:Cassandra, PHP, 資訊學習

其他

關於我  (About me)

小額贊助

  文章 RSS Feed

  留言 RSS Feed

Apache AWS Bash C/C++ Docker FreeBSD GCP Git Google Java JavaScript Laravel Linux Microsoft MSSQL MySQL Nginx PHP PHPUnit PostgreSQL Python Qt Ubuntu Unix Vim Web Windows WordPress XD 作業系統 分享 好站推薦 專題 攝影 新奇搞笑 新聞 旅遊 生活雜記 程式設計 網路架站 網頁設計 資訊學習 資訊安全 遊戲 音樂


創用 CC 授權條款
本著作係採用創用 CC 姓名標示-相同方式分享 4.0 國際 授權條款授權.