使用CQL在Cassandra中的宽行 - 得到奇怪的错误

时间:2013-02-10 21:14:11

标签: node.js cassandra cql

我正在尝试为Cassandra中的博客存储评论,并提出了这种模式(从here获得了想法):

create table comments ( slug varchar, ts timestamp, value text, primary key (slug,ts));

使用CQL(我正在使用带有Helenus驱动程序的node.js)我正在尝试添加一些数据,这是我到目前为止所得到的:

var helenus = require('helenus'),
    pool = new helenus.ConnectionPool({
        hosts: ['localhost:9160'],
        keyspace: 'blogks'
    });

pool.on('error', function(err) {
    console.error(err.name, err.message);
});



module.exports.addComment = function(slug, comment,callback){
    pool.connect(function(connErr,keyspace){
        if(connErr){
            callback(connErr);
            return;
        }

        var cql = "INSERT INTO comments (slug,ts,value) VALUES (?, ?, ?);";
        pool.cql(cql,[slug,serializeDate(new Date()),serializeJSON(comment)],function(err,results){
            callback(err,results);
        });
    });
}

function serializeDate(date){
    var dateSerializer = new helenus.Marshal('DateType');
    return dateSerializer.serialize(date).toString('hex');
}

function serializeJSON(data){
    var utf8Serializer = new helenus.Marshal('UTF8Type');
    return utf8Serializer.serialize(JSON.stringify(data)).toString("hex");
}

您可以将注释json对象传递给此方法,然后将其推送到cassandra。我这样称呼它来测试:

var comments = require('./comments.js');

comments.addComment("myslug",{id:2,name:"Alex",comment:"Hello!"},function(e,r){
    console.log(e);
    console.log(r);
})

但每当我这样做时(我尝试了各种CQL驱动程序),我都会收到这个神秘的错误消息:

[HelenusInvalidRequestException: unable to coerce 'value' to a  formatted date (long)] name: 'HelenusInvalidRequestException'

我尝试将时间戳更改为所有不同的数据类型,但没有运气。非常奇怪的是,起初,我的主键只是slug本身,然后它确实有效。但是,我想将所有注释存储在按时间戳排序的一行中,因此我不得不采用这种方法使用两列作为主键。有什么想法吗?

编辑所以基于rs_atl's建议,这是我尝试过的:

这一行:

dateSerializer.serialize(date).toString('hex')
实际上确实返回垃圾(0000013ccfacf5c4),我一定误解了如何使用API​​。所以这就是我试过的:

我试过new Date().getTime()这实际上在JS中确实返回了Unix风格的纪元,但是这不起作用我得到了同样的错误。然后我尝试使用moment.js来尝试格式化字符串:

moment().format("YYYY-MM-DD HH:mm:ss")

似乎正在返回正确的格式,但又一次。同样的错误。然后我尝试了这个:

moment().format("YYYY-MM-DD HH:mm") + "Z"
没有运气。然后我尝试了这个:

moment().format("YYYY-MM-DD HH:mmZ")

实际上确实在最后添加了时区信息,但仍然没有运气。有什么想法吗?

3 个答案:

答案 0 :(得分:1)

我不确定这一行的输出是什么:

return dateSerializer.serialize(date).toString('hex');

但这就是您的问题所在。您似乎没有输出Cassandra理解的有效日期。有效日期为:

  1. Unix风格的时代作为长值。

  2. 以下表格之一的字符串:

    yyyy-mm-dd HH:mm
    yyyy-mm-dd HH:mm:ss
    yyyy-mm-dd HH:mmZ
    yyyy-mm-dd HH:mm:ssZ
    YYYY-MM-dd'T'HH:毫米
    YYYY-MM-dd'T'HH:MMZ
    YYYY-MM-dd'T'HH:MM:SS
    YYYY-MM-dd'T'HH:MM:SSZ
    YYYY-MM-DD
    YYYY-MM-DDZ

  3. 检查以确保您正在编写其中一种有效的时间戳类型。

答案 1 :(得分:1)

您似乎使用了错误的CQL版本。您希望使用CQL 3.0.0,但驱动程序默认使用CQL2。您需要在初始化中指定正确的CQL版本。

pool = new helenus.ConnectionPool({
    hosts: ['localhost:9160'],
    keyspace: 'blogks',
    cqlVersion: '3.0.0'
});

另外请确保您使用的是Helenus的最新版本(截至目前为0.6.2)。

答案 2 :(得分:0)

对于时间戳,我总是用毫秒来表示时间。

尝试:

Date.now()

而不是:

serializeDate(new Date())