Широкие строки в Cassandra с использованием CQL - странная ошибка

Я пытаюсь хранить комментарии для блога в Cassandra и придумал эту схему (идея взята из здесь):

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

Используя CQL (я использую node.js с драйвером Helenus), я пытаюсь добавить некоторые данные к этому, вот что у меня есть до сих пор:

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'

Я попытался изменить временную метку, чтобы она была разными типами данных, но безуспешно. Очень странно то, что сначала моим первичным ключом был просто сам слаг, а потом он заработал. Однако я хочу хранить все комментарии в одной строке, упорядоченные по отметке времени, поэтому мне пришлось использовать этот подход с использованием двух столбцов для первичного ключа. Есть идеи?

EDIT Итак, основываясь на предложении rs_atl, вот что я пробовал:

Эта строка:

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")

что на самом деле добавляет информацию о часовом поясе в конце, но все равно не повезло. Есть идеи?


person BFree    schedule 10.02.2013    source источник
comment
Вы точно знаете, что у вас нет проблемы с порядком байтов?   -  person rs_atl    schedule 12.02.2013
comment
@rs_atl Хм ... Я недостаточно знаю о порядке следования байтов, чтобы ответить на этот вопрос. Лучшее, что я могу сделать, это указать вам на строку кода в Helenus, которая кодирует даты (из того, что я могу сказать, это просто получение эпохи в стиле unix и кодирование ее как длинной). github.com/simplereach/helenus/blob/master/ библиотека/маршал/   -  person BFree    schedule 13.02.2013


Ответы (3)


похоже, вы используете неправильную версию CQL. Вы предполагаете использовать CQL 3.0.0, но драйвер по умолчанию использует CQL2. При инициализации необходимо указать правильную версию CQL.

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

Также убедитесь, что вы используете последнюю версию (на данный момент 0.6.2) Helenus.

person Russ Bradberry    schedule 12.02.2013
comment
Спасибо! Действительно ценю это. - person BFree; 13.02.2013

Я не совсем уверен, что такое вывод этой строки:

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

но это где ваша проблема. Похоже, вы не выводите действительную дату, которую понимает Кассандра. Действительная дата:

  1. Эпоха в стиле Unix в виде длинного значения.

  2. Строка в одной из следующих форм:

    гггг-мм-дд ЧЧ:мм
    гггг-мм-дд ЧЧ:мм:сс
    гггг-мм-дд ЧЧ:ммZ
    гггг-мм-дд ЧЧ:мм:ссZ
    гггг- мм-дд'T'ЧЧ:мм
    гггг-мм-дд'T'ЧЧ:ммZ
    гггг-мм-дд'T'ЧЧ:мм:сс
    гггг-мм-дд'T' ЧЧ:мм:ссZ
    гггг-мм-дд
    гггг-мм-ддZ

Убедитесь, что вы пишете один из этих допустимых типов меток времени.

person rs_atl    schedule 11.02.2013
comment
Спасибо за участие и попытку помочь. Смотрите мое обновление, я пробовал ваши предложения, но все равно не повезло :( - person BFree; 12.02.2013

Для временных меток я всегда использую int в миллисекундах для представления времени.

Пытаться:

Date.now()

вместо:

serializeDate(new Date())
person SimpleSeeker    schedule 20.03.2013