2015-07-10 92 views
5

我试图显示传感器列表中的最新值。该列表还应该可以通过时间戳进行排序。通过Cassandra中的时间戳订购最新记录

我尝试了两种不同的方法。我包括传感器的在主键的更新时间:

CREATE TABLE sensors (
    customerid int, 
    sensorid int, 
    changedate timestamp, 
    value text, 
    PRIMARY KEY (customerid, changedate) 
) WITH CLUSTERING ORDER BY (changedate DESC); 

然后我可以选择列表是这样的:

select * from sensors where customerid=0 order by changedate desc; 

这导致这样的:

customerid | changedate    | sensorid | value 
------------+--------------------------+----------+------- 
      0 | 2015-07-10 12:46:53+0000 |  1 |  2 
      0 | 2015-07-10 12:46:52+0000 |  1 |  1 
      0 | 2015-07-10 12:46:52+0000 |  0 |  2 
      0 | 2015-07-10 12:46:26+0000 |  0 |  1 

问题是,我没有得到最新的结果,但也得到了所有的旧值。

如果我从主键中删除更改,则select一起失败。

InvalidRequest: code=2200 [Invalid query] message="Order by is currently only supported on the clustered columns of the PRIMARY KEY, got changedate" 

更新的传感器值也没有选项:

update overview set changedate=unixTimestampOf(now()), value = '5' where customerid=0 and sensorid=0; 
InvalidRequest: code=2200 [Invalid query] message="PRIMARY KEY part changedate found in SET part" 

失败的原因CHANGEDATE是主键的一部分。

是否有任何可能的方法来存储每个传感器的最新值,并且还通过时间戳记来保存表格?

编辑: 在此期间,我尝试了另一种方法,只存储最新值。

我用这个模式:

CREATE TABLE sensors (
    customerid int, 
    sensorid int, 
    changedate timestamp, 
    value text, 
    PRIMARY KEY (customerid, sensorid, changedate) 
) WITH CLUSTERING ORDER BY (changedate DESC); 

将最新的值之前,我会删除所有旧值

DELETE FROM sensors WHERE customerid=? and sensorid=?; 

但这种失败,因为changedate没有WHERE子句的一部分。

+0

这似乎是经典检索每组问题中的最后一条记录。即获取每个sensorID的最新读数。 – malhal

回答

2

问题是,我没有得到最新的结果,而是所有的旧值。

既然你是在DESC的聚簇顺序存储,它总是会很容易得到最新的记录,所有你需要做的是“限制”添加到您的查询,即:

select * from sensors where customerid=0 order by changedate desc limit 10; 

最多可以返回10条记录,其中包含最多的记录。即使您使用限制,但您仍然保证获得最新记录,因为您的数据是以这种方式订购的。

如果我从主键中删除changedate,select会一起失败。

这是因为你不能在不是集群密钥(主键的次要部分)的列上排序,除了可能有一个辅助索引,我不建议这样做。

更新传感器数值也没办法

你的更新查询失败,因为它是不合法的,包括在“设置”中的主键的一部分。为了使这项工作,所有你需要做的就是更新您的查询,包括在where子句中CHANGEDATE,即:

update overview set value = '5' and sensorid = 0 where customerid=0 and changedate=unixTimestampOf(now()) 

有只存储从每个传感器的最新值,并保留任何可能的方式表按时间戳排序?

您可以通过创建一个名为'latest_sensor_data'的独立表格,使用与主键例外相同的表格定义来执行此操作。主键现在是'customerid,sensorid',因此每个传感器只能有一个记录。创建单独表格的过程称为denormalization,并且是Cassandra数据建模中的常见使用模式。当您插入传感器数据时,您现在可以将数据插入'传感器'和'latest_sensor_data'中。

CREATE TABLE latest_sensor_data (
    customerid int, 
    sensorid int, 
    changedate timestamp, 
    value text, 
    PRIMARY KEY (customerid, sensorid) 
); 

在卡桑德拉3.0 'materialized views'将出台,这将使这个不必要的,因为你可以使用物化视图来完成这个要求。

现在做下面的查询:

select * from latest_sensor_data where customerid=0 

会给你每个传感器为客户的最新值。

我建议将'传感器'重命名为'sensor_data'或'sensor_history',以使其更清楚数据是什么。此外,您应该将主键更改为'customerid,changedate,sensorid',因为这可以让您在同一日期有多个传感器(这似乎是可能的)。

+0

另一个说明,如果你想要更多的最新值(即最后10个值),它会变得更加困难。在C * 2.2中,您可以使用用户定义的聚合来让cassandra为您的传感器表获取每个传感器的10个“最新”值。你也可以看看使用spark-cassandra连接器来偶尔为你计算。 –

+0

你的建议的问题是,我放弃了用'changedate'排序的能力。 – user5102859

+0

我提出了两个表,其中一个在changedate('sensor_history'表)上有一个聚簇键,另一个聚集在sensorid上。 –

2

您的第一种方法看起来很合理。如果您向查询添加“限制1”,则只会获得最新结果,或限制2以查看最新的2个结果等。

如果要从表中自动删除旧值,则可以指定插入时的数据点的TTL(生存时间)。因此,如果您想保留10天的数据点,您可以在插入语句中添加“USING TTL 864000”。或者你可以为整个表设置默认的TTL。

+0

这里我不能使用TTL,因为没有保证的时间跨度,传感器报告值。它可能保持沉默几天,几周甚至几个月。但我仍然需要保留最新的价值。 – user5102859

+0

我认为OP需要每个sensorID的最新版本。 – malhal