【问题标题】:Querying columns with prefix not working using Astyanax使用 Astyanax 查询带有前缀的列不起作用
【发布时间】:2013-04-09 19:15:59
【问题描述】:

我有一个方案如下:

  • 时间戳
  • 设备 ID
  • 设备名称
  • 设备所有者
  • 设备位置

我使用 CQL 创建了这个列族,并将主键定义为 (TimeStamp,Device ID, Device Name)。通过具有 DeviceID、名称和字段名称(存储Device OwnerDevice Location)字段的可序列化对象。我使用 Astyanax 插入了一些记录。

根据我的理解,一行的列是通过将Device IDDevice 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),尝试=1]InvalidRequestException(为什么:没有足够的字节来读取组件 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;
}

按照上述类的结构,我可以看到列族中的列: 列名:dev\:01\:02:1:location 列值:00000001

仅供参考,使用 astyanax 1.56.31

【问题讨论】:

  • 您可以粘贴您的创建表语句吗?问题是你的列类型是 CompositeType 所以你需要在不使用 CQL 时进行序列化。
  • @Michael Härtl 这是我的创建表语句:CREATE TABLE perf_sample (stime ascii, devName ascii, devId int, devOwner int, devLocation int, PRIMARY KEY (stime, devName, devID))
  • 问题已了解。我也看过你的另一篇文章,所以如果你能分享一些 CF 数据会更好,这样任何人都可以在他们的本地进行测试,并可能以有效的方式帮助你。
  • @abhi 我已经添加了有关上述数据的信息

标签: cassandra astyanax


【解决方案1】:

您可以将 PlayOrm 用于 cassandra(我听说最新版本现在也在 mongodb 上工作)。使用它,您可以创建一个实体并将 @NoSqlPartitionByField 注释添加到 beginOfMonthTimestamp 和 deviceId 列,此外还有时间戳列。然后,您可以像这样查询分区

PARTITIONS s('time', :partitionId) select s from TABLE as s where s.deviceName='mike'

仅当您确定您的分区不会超过数百万时,才可以这样做。你可以有无限的分区。所以基本上,你可以使用 beginOfMonth 或 beginOfWeek ,这取决于东西进入系统的速度。有更多信息在

http://buffalosw.com/wiki/playorm-documentation/

【讨论】:

  • 我也尝试过使用 playOrm,但出现了奇怪的问题。我在表格中插入了一些值,但是当我尝试读取它时,结果有点奇怪。有时它会返回所有的列,但其他的都没有。
  • 您可以在单独的问题中发布这些问题,您一定会得到一些帮助。
【解决方案2】:

这里有两件事,
1. 您在设备 ID 中使用“:”,Cassandra 也将其用于复合列。因此,如果可以,请避免使用它。
2. 根据您的测试数据,您的列名显示为“dev\:01\:02:1:location”,即 devicename+deviceid+location。但是您在查询中给出了 deviceID+deviceName+"_\u00000"??

【讨论】:

  • 抱歉打错了。在查询中,我将其用作“设备名称+设备 ID+位置”。我将尝试删除名称中的“:”,看看它是否有效。谢谢!
  • 删除 ':' 也无济于事!!
  • 您是如何创建列族的?
【解决方案3】:

为了克服这个问题,我改变了在表中存储数据的方式。我没有使用复合主键,而是更改了架构,以便只有单个主键和动态列。所以,现在我在时间上有主键,我的列名是由我的插入代码显式动态构造的。例如。 "dev\:01\:02:1:location" 和以前一样,但这完全消除了对序列化对象的需求。到目前为止,这已经解决了我的问题。让我们看看它会带来什么问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 2013-02-03
    • 1970-01-01
    • 2018-07-14
    • 2012-04-04
    • 2017-05-09
    • 2023-03-26
    相关资源
    最近更新 更多