json - 使用 python 客户端将 JSON 数据写入 Cassandra,主键选择问题

标签 json cassandra cassandra-3.0

所以我想将编码为 JSON 字符串的数据写入 Cassandra 表中。我做了以下步骤:

  • 创建一个 Cassandra 表,其中包含具有我的 JSON 字符串的所有属性的列。这是 cql:
CREATE TABLE on_equipment (
  ChnID varchar,
  StgID varchar,
  EquipID varchar,
  SenID varchar,
  value1 float,
  value2 float,
  value3 float,
  electric_consumption float,
  timestamp float,
  measurement_location varchar,
  PRIMARY KEY ((timestamp))
) WITH comment = 'A table for the on equipment readings';
  • 编写一个 Python Cassandra 客户端,将数据从 JSON 负载写入 Cassandra。 这是进行 INSERt 查询的代码片段(msg.value 是 json 字符串):
session.execute('INSERT INTO ' + table_name + ' JSON ' + "'" + msg.value + "';")

执行此操作时我没有出现任何书写错误。

但是,我遇到了一个问题:

我拥有的 JSON 数据来自 IoT 源,我拥有的属性之一是 unix 时间戳。 JSON 记录的示例如下(注意时间戳属性):

{'timestamp': 1598279069.441547, 'value1': 0.36809349674042857, 'value2': 18.284579388599308, 'value3': 39.95615809003724, 'electric_consumption': 1.2468644044844224, 'SenID': '1', 'EquipID': 'MID-1', 'StgID': '1', 'ChnID': '1', 'measurement_location': 'OnEquipment'}

为了插入多条记录,我在Cassandra表中定义了时间戳值作为数据的主键。问题是并非所有记录都被写入 Cassandra,只有时间戳属于特定组的记录。我知道这一点是因为我已经生成了大约 100 条消息并且收到了零个写入错误,但表格的内容只有 4 行:

 timestamp  | chnid | electric_consumption | equipid | measurement_location | senid | stgid | value1   | value2   | value3
------------+-------+----------------------+---------+----------------------+-------+-------+----------+----------+----------
 1.5983e+09 |     1 |             0.149826 |   MID-1 |          OnEquipment |     1 |     1 | 0.702309 | 19.92813 | 21.47207
 1.5983e+09 |     1 |              1.10219 |   MID-1 |          OnEquipment |     1 |     1 | 0.141921 |  5.11319 | 78.17094
 1.5983e+09 |     1 |              1.24686 |   MID-1 |          OnEquipment |     1 |     1 | 0.368093 | 18.28458 | 39.95616
 1.5983e+09 |     1 |              1.22841 |   MID-1 |          OnEquipment |     1 |     1 | 0.318357 |  16.9013 |  71.5506

换句话说,Cassandra 正在更新这四行的值,而此时它应该写入所有 100 条消息。

我的猜测是我错误地使用了 Cassandra 主键。时间戳列是 float 类型。

我的问题: 这种行为有意义吗?你能解释一下吗? 我可以使用什么作为主键来解决这个问题? 有没有办法让主键成为 Cassandra 写入或到达时间?

预先感谢您的帮助!

最佳答案

您已将主键定义为时间戳 - 如果您将数据插入 Cassandra 表,并且您正在写入的数据与表中已有数据具有相同的主键,您将覆盖它。所有插入实际上都是插入/更新,因此当您第二次使用相同的主键值时,它会更新。

至于解决方案 - 这很诡异 - 主键必须符合它的名称 - 它是主要的,例如唯一 - 即使它是时间戳而不是 float ,您也应该在主键中至少有 1 个其他字段(例如 IoT 唯一标识符),以便在完全相同的时间从两个不同设备读取的 2 个读数不会发生冲突.

在 Cassandra 中,您可以根据您打算如何访问数据来对数据和键进行建模 - 不知道不可能知道主键(分区 + 集群键)应该是什么。理想情况下,您还需要了解有关数据基数和选择性的信息。

识别并定义您打算对数据运行的查询,这应该指导您的分区键和集群键选择 - 它们共同构成主键。

这里要添加到上面的具体问题是数据超出了 float 可以存储的精度 - 限制有效值并使它们全部相同。如果将 float 更改为 double,它会存储数据而不将值限制为相同的值 - 这会导致更新插入而不是插入新行。 (JSON 插入部分与问题无关,因为它发生了)

重现问题如下:

 CREATE TABLE on_equipment (
  ChnID varchar,
  timestamp float,
  PRIMARY KEY ((timestamp))
) ;

insert into on_equipment(timestamp, chnid) values (1598279061,'1');
insert into on_equipment(timestamp, chnid) values (1598279062,'2');
insert into on_equipment(timestamp, chnid) values (1598279063,'3');
insert into on_equipment(timestamp, chnid) values (1598279064,'4');

select count(*) from on_equipment;

1

select timestamp from on_equipment;

1.59827904E9

您可以看到该值已四舍五入并设置了上限,所有 4 个值的上限相同,如果您使用较小的数字作为时间戳,它会起作用,但这样做不是很有用。

将其更改为双数:

CREATE TABLE on_equipment (
  ChnID varchar,
  timestamp double,
  PRIMARY KEY ((timestamp))
) ;

insert into on_equipment(timestamp, chnid) values (1598279061,'1');
insert into on_equipment(timestamp, chnid) values (1598279062,'2');
insert into on_equipment(timestamp, chnid) values (1598279063,'3');
insert into on_equipment(timestamp, chnid) values (1598279064,'4');

select count(*) from on_equipment;

4

关于json - 使用 python 客户端将 JSON 数据写入 Cassandra,主键选择问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63565125/

相关文章:

c# - 使用Unity JsonUtility反序列化JSON数组获取序列化值失败

java - 使用 Java Oracle 7 运行 cassandra 1.1.9 时出现问题

nosql - Cassandra 的样本数据模型?

c# - 尝试使用 C# 中的 Guid 作为 Cassandra 中的主键

javascript - 如果不包含父 key ,则无法获取 Firebase 输出

json - 坚持尝试为私有(private)组织存储库创建 package.json

javascript - 从 json 文件获取更少/匹配的对象

elasticsearch - 用户网格系统要求?

cassandra - 如何设计 NoSQL 数据库以按时间戳选择数据顺序

java - 如何使用 Cassandra Java 驱动程序访问带有嵌套映射的列表