2017-01-24 32 views
1

我想弄清楚如何查询cassandra在特定的日期与java 8 api的分钟间隔。Cassandra查询时间戳列返回没有值与Java的即时类型

例如,假设我有一个组表。

create table groups(
group_name text, 
updated_on timestamp 
primary key (group_name, updated_on) 
); 

我有表

group_name updated_on 
RealGroup  2017-01-01 04:30:00-0800 
RealGroup  2017-01-01 04:30:15-0800 
MockGroup  2017-02-05 04:30:00-0800 

我想执行一个查询到类似下面卡桑德拉内的下列记录。

select * from groups where group_name = 'RealGroup' and updated_on >= 2017 01-01 04:30:00-0800 AND <= 2017-01-01- 04:30:59-0800' 

所以基本上,我想获得关于分钟间隔的数据。

我正在使用GroupAccessor和datastax api。

@Query("SELECT * FROM GROUPS WHERE GROUP_NAME = :groupName AND UPDATED_ON>= :startDate AND UPDATED_ON<= :endDate") 
Result<Group> getResults(@Param("groupName") String groupName, @Param("startDate") Instant startDate, @Param("endDate") Instant endDate); 

我的问题是,客户的电话会是什么样子?什么是用java 8 api发送请求的正确方法?

我正在使用以下,但它给我奇怪的结果。

LocalDateTime startDate = LocalDateTime.of(2017, Month.JANUARY, 1, 4, 30); 
LocalDateTime endDate = LocalDateTime.of(2017, Month.JANUARY, 1, 4, 31); 
Instant start = startDate.toInstant(ZoneOffset.UTC); 
Instant end = endDate.toInstant(ZoneOffset.UTC); 

Result<Group> dateGroup = groupAccessor.getResults("RealGroup", start, end); 

所以实际上,上面的代码应该返回2行。

RealGroup  2017-01-01 04:30:00-0800 
RealGroup  2017-01-01 04:30:15-0800 

但是没有返回。

+0

_Odd_怎么样?什么是意外? –

+0

退货是空的。 – user1172490

+0

代替'ZoneOffset.UTC',你想要一个'ZoneOffset'来代表你在你的CQL查询中拥有的'-0800'。 –

回答

2

您正在聚类在timestamp类型的列上。所述timestamp类型表示

以来被称为 划时代标准的基本时间的毫秒数:1970年1月1日在00:00:00 GMT

当使用CQLSH,可以使用一个整数表示毫秒数

INSERT INTO groups (group_name , updated_on) VALUES ('MockGroup', 1485221928341); 

或价值,你可以使用

在以下任何ISO 8601种格式的文本字符串:

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:mm 
yyyy-mm-dd'T'HH:mmZ 
yyyy-mm-dd'T'HH:mm:ss 
yyyy-mm-dd'T'HH:mm:ssZ 
yyyy-mm-dd'T'HH:mm:ss.ffffffZ 
yyyy-mm-dd 
yyyy-mm-ddZ 

其中Z是RFC-822 4位数字的时区,表示从UTC

时区的差别在你的榜样,您已指定

2017 01-01 04:30:00-0800 

其中包含UTC时间后8小时的时区。但是,当您用Java代码发出请求时,您创建了一个Instant,意思是代表UTC时区的4:30当地时间(即0偏移量)。这是什么

Instant start = startDate.toInstant(ZoneOffset.UTC); 

呢。所以你的数据库实际上只有8个小时。相反,从当地时间4:30 UTC时间8小时的时区创建Instant

Instant start = startDate.toInstant(ZoneOffset.ofHours(-8)); 
Instant end = endDate.toInstant(ZoneOffset.ofHours(-8)); 

这应该让你回到你想要的两组。

有没有一种方法,我不必处理区域?

是的,使用整数(就像我的第一个例子)。关于普通数字比格式化字符串更难推理。

或者,您可以在日期字符串的末尾使用Z来指示没有偏移UTC的祖鲁时区。例如,

INSERT INTO groups (group_name , updated_on) VALUES ('MockGroup', '2017-02-05 04:31:00Z'); 

显然,从Java代码中,Instant没有时区的概念,它只是代表了一个时间戳,就像在卡桑德拉的类型,这样你就可以直接使用它。

+0

当我使用datastax的驱动程序保存即时记录时,cassandra中的时间戳记值总是以人类易读的格式显示,即'2017-01-23 06:40:43-0800',而不是以毫秒为单位的整数。你如何改变它? – user1172490

+0

@ user1172490这就是CQLSH显示它的方式。 [Here](http://stackoverflow.com/questions/28547616/cassandra-cqlsh-how-to-show-microseconds-milliseconds-for-timestamp-columns)是一个把它打印成整数的技巧。 –