Кассандра поиск по дате из столбца метки времени

#cassandra

Вопрос:

из таблицы Cassandra, как получить записи на основе даты из столбца метки времени.Подробности в таблице

    CREATE TABLE hlragent_logs.hlragent_logs_2021 (
    msisdn text,
    date_time timestamp,
    cmd_no text,
    agent_id text,
    cmd_executed text,
    dummy text,
    id bigint,
    imsi text,
    mml_cmd text,
    module text,
    node text,
    node_id text,
    node_ip text,
    p text,
    pno text,
    serial text,
    vhlr_name text,
    PRIMARY KEY (msisdn, date_time, cmd_no)
) WITH CLUSTERING ORDER BY (date_time ASC, cmd_no ASC)
    AND bloom_filter_fp_chance = 0.01
    AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}
    AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND crc_check_chance = 1.0
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99PERCENTILE';
CREATE INDEX indx_agentlogs_2021 ON hlragent_logs.hlragent_logs_2021 (imsi)
 

выберите * из hlragent_logs_2021, где todate(дата и время)=»2021-08-10″ разрешить фильтрацию;
Исключение синтаксиса: строка 1:45 нет жизнеспособной альтернативы на входе ‘(‘ (выберите * из hlragent_logs_2021, где указать

Ответ №1:

Вы не можете использовать пользовательские функции в WHERE предложении (для этого есть билет Jira, но я не помню, чтобы кто-то работал над ним).

Комментарии:

1. todate-это функция отметки времени для управления датами, используемыми в операторах INSERT, UPDATE и SELECT. выберите * из hlragent_logs_2021, где date_time>=’2021-08-10′ и mml_cmd=’УДАЛИТЬ ПОЛЬЗОВАТЕЛЯ» разрешить фильтрацию это уокинг

2. Я знаю, что todate это такое — вы просто не можете использовать его в состоянии «где». Вы можете изучить грамматику CQL, чтобы убедиться, что функции не поддерживаются: github.com/apache/cassandra/blob/trunk/src/antlr/Parser.g#L1672

Ответ №2:

Нет необходимости использовать собственную TODATE() функцию CQL для работы со столбцами временных меток. Можно напрямую работать с колонкой с помощью:

 SELECT * FROM ... WHERE ... AND date_time < "2021-08-10";
 

Но вы не можете использовать оператор равенства ( = ), потому что тип данных метки времени CQL кодируется как количество миллисекунд с эпохи Unix (1 января 1970 года 00:00 по Гринвичу), поэтому вам нужно быть точным при работе с метками времени.

В зависимости от того, где вы выполняете запрос, фильтр может быть переведен в местный часовой пояс. Позвольте мне проиллюстрировать это примером таблицы:

 CREATE TABLE community.tstamptbl (
    id int,
    tstamp timestamp,
    PRIMARY KEY (id, tstamp)
)
 

Эти 2 утверждения могут показаться похожими, но переводятся в 2 разные записи:

 INSERT INTO tstamptbl (id, tstamp) VALUES (5, '2021-08-09');
 
 INSERT INTO tstamptbl (id, tstamp) VALUES (5, '2021-08-09  0000');
 

Первая инструкция создает запись с меткой времени в моем локальном часовом поясе (Мельбурн, Австралия), в то время как вторая инструкция создает запись с меткой времени в формате UTC ( 0000 ):

 cqlsh:community> SELECT * FROM tstamptbl WHERE id = 5;

 id | tstamp
---- ---------------------------------
  5 | 2021-08-08 14:00:00.000000 0000
  5 | 2021-08-09 00:00:00.000000 0000
 

Точно так же вам нужно быть точным при считывании данных. Вам нужно указать часовой пояс, чтобы устранить двусмысленность. Вот несколько примеров:

 SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-09  0000';
SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-10 12:00 0000';
SELECT * FROM tstamptbl WHERE id = 5 AND tstamp < '2021-08-08 12:34:56 0000';
 

Опять же, поскольку временные метки кодируются в миллисекундах (вместо дней), существует целый диапазон возможных значений для данной даты. Если я хотел получить все строки для даты 2021-08-09 , мне нужно отфильтровать их на основе диапазона, как в этом примере:

 SELECT * FROM tstamptbl 
WHERE id = 5
    AND tstamp >= '2021-08-09  0000'
    AND tstamp < '2021-08-10  0000';
 

Ваше здоровье!