DjangoCassandraModel使用ORDER BY报错,如何获取时间主键的最新记录
报错原因
你当前的表结构中time是唯一主键,也就是time同时作为分区键,没有设置聚类键。Cassandra的ORDER BY仅支持对聚类键使用,且使用前必须指定分区键的等值或IN过滤条件,因此直接对分区键执行ORDER BY会触发该报错。
解决方案
提供两种可选方案,可根据业务场景选择:
方案1:调整表结构(推荐,性能更优)
时序场景下推荐使用复合主键,将time设为降序聚类键,单次查询即可直接拿到最新记录:
- 新增一个固定值的分区键(单表数据量小于100万条时可直接使用,数据量过大可替换为按天/周分桶的分区键)
- 将
time设置为聚类键并指定降序存储,表中默认返回的第一条数据就是最新记录
修改后的完整代码如下:
from cassandra.cqlengine import columns from django_cassandra_engine.models import DjangoCassandraModel from django.db import connections def get_tag(car_name, car_type): class Tag(DjangoCassandraModel): __table_name__ = f"{car_name}_{car_type}" __keyspace__ = "mydatabase" # 固定分区键,数据量大时可替换为按日期分桶的字段 dummy_partition = columns.Integer(primary_key=True, partition_key=True, default=1) # 聚类键,降序存储,默认返回的第一条就是最新数据 time = columns.Integer(primary_key=True, clustering_order="DESC", required=True) value = columns.Float(required=True) @classmethod def last(cls): with connections['cassandra'].cursor() as cursor: elem = cursor.execute(f"SELECT time, value FROM {cls.__table_name__} WHERE dummy_partition=1 LIMIT 1;") return elem.one() if elem else None def __str__(self) -> str: return f"{self.time},{self.value}" # 自动同步表结构,不需要手动写CREATE TABLE语句 Tag.sync_table() return Tag
调用方式和之前完全一致:
tag = get_tag(car_name, car_type) last_elem = tag.last()
方案2:不修改现有表结构(适合不想迁移历史数据的场景)
不需要调整表结构,通过两次查询实现需求:先查询最大的time值,再用该值查询对应的记录,修改last方法即可:
@classmethod def last(cls): with connections['cassandra'].cursor() as cursor: # 第一步查询最大时间戳 max_time_res = cursor.execute(f"SELECT MAX(time) as max_time FROM {cls.__table_name__};") max_time = max_time_res.one().max_time if not max_time: return None # 第二步查询对应时间的记录 elem = cursor.execute(f"SELECT time, value FROM {cls.__table_name__} WHERE time = %s;", [max_time]) return elem.one()
内容的提问来源于stack exchange,提问作者user7429643
相关产品推荐
相关产品推荐

