我的计划如下:
我使用CQL创建了此列系列,并将主键定义为(TimeStamp,Device ID, Device Name)
。通过可序列化对象,该对象具有DeviceID,名称和字段名称(存储Device Owner
或Device Location
)的字段。我使用Astyanax插入了一些记录。
根据我的理解,行的列是通过将Device ID
,Device Name
和字段名称组合为列名来创建的,并将值作为该特定字段的值。
因此,对于特定时间戳和设备,列名称将采用模式(Device ID:Device Name: ...)
。
所以我相信我们可以使用这两个字段作为前缀来获取特定时间 - 设备组合的所有条目。
我使用以下查询来获取结果:
RowSliceQuery<String, ApBaseData> query = adu.keyspace
.prepareQuery(columnFamily)
.getKeySlice(timeStamp)
.withColumnRange(new RangeBuilder()
.setStart(deviceID+deviceName+"_\u00000")
.setEnd(deviceID+deviceName+"_\uffff")
.setLimit(batch_size)
.build());
但是在执行上述查询时,我得到以下异常:
BadRequestException:[host = localhost(127.0.0.1):9160,latency = 6(6),attempts = 1] InvalidRequestException(why:没有足够的字节来读取组件0的值)
@abhi此列系列中的数据如下:
stime | devName | devId | Owner | Location
1361260800 | dev:01:02 | 1 | 1234 | 1
1361260800 | dev:02:03 | 2 | 34 | 2
1361260800 | dev:05:06 | 1 | 12 | 1
1361260800 | dev:03:02 | 2 | 56 | 3
我正在使用的java可串行java类是:
public class BaseData implements Serializable {
private static final long serialVersionUID = 1L;
@Component(ordinal = 0)
private String devName;
@Component(ordinal = 1)
private int devID;
@Component(ordinal = 2)
private String field;
}
按照上面类的结构,我可以看到列族中的列为: Columne名称:dev \:01 \:02:1:location列值:00000001
仅供参考,使用astyanax 1.56.31
答案 0 :(得分:1)
您可以将PlayOrm用于cassandra(我听说最新版本也在使用mongodb)。使用它可以创建一个实体并将@NoSqlPartitionByField注释添加到beginOfMonthTimestamp和deviceId列,另外还有timestamp列。然后,您可以查询分区,如此
PARTITIONS s('time',:partitionId)从TABLE中选择s作为s,其中s.deviceName ='mike'
只有在您确定分区不会超过数百万时,才可以。你可以拥有无限的分区。基本上,您可以使用beginOfMonth或beginOfWeek,具体取决于进入系统的内容的速度。
有更多信息答案 1 :(得分:1)
这里有两件事,
1.您在设备ID中使用“:”,Cassandra也将其用于复合列。因此,如果可以,请避免使用它
2.您的列名称为“dev \:01 \:02:1:location”,根据您的测试数据,它是devicename + deviceid + location。但是,您在查询中提供了deviceID + deviceName +“_ \ u00000”
答案 2 :(得分:0)
为了克服这个问题,我改变了在表格中存储数据的方式。我没有使用复合主键,而是更改了架构,以便只有一个主键和动态列。所以,现在我在stime上有主键,我的列名是由我的插入代码动态显式构造的。例如。 “dev \:01 \:02:1:location”与之前的方式相同,但这完全消除了对序列化对象的需求。这已经解决了我现在的问题。让我们看看它后来会出现什么问题。