列的注解@ClusteringColumn的排序值无效?

yc0p9oo0  于 2022-09-27  发布在  Cassandra
关注(0)|答案(3)|浏览(115)

我使用的是Cassandra 2.2.1。我有一个表job_status,键如下:
主键(job_id,is_complete,last_run_at),按群集顺序(is_comcomplete ASC,last_roun_at DESC)
我有以下java类:

@Table(keyspace = "storakle", name = "import_job_status")
public class JobStatus
{
    @PartitionKey
    @Column(name = "job_id")
    private String jobId;   

    @ClusteringColumn
    @Column(name = "is_complete")
    private boolean isComplete;

    @ClusteringColumn
    @Column(name = "last_run_at")
    private Date lastRunAt;

    @Column(name = "run_number_of_times")
    private int runNumberOfTimes;
}

我想通过Cassandra Java驱动程序中的Mapper类查询job_status表,如下所示:

public JobStatus getIncompleteJobStatusById(String jobId)
{
        Mapper<JobStatus> mapper = new   MappingManager(_cassandraDatabaseManager.getSession()).mapper(JobStatus.class);

        boolean isComplete = false;
        JobStatus jobStatus = mapper.get(jobId, isComplete);

        return jobStatus;
}

但是,我得到以下错误:
列lastRunAt的注解@ClusteringColumn的排序值0无效,应为1
我明白为什么会这样。Map器获取JobStatus类中注解的所有主键和集群键,并在调用时进行检查,以获取是否在Map器中提供了键。get方法与注解类中的键的编号相同。
但我认为,在Cassandra中,只要您省略的聚类键位于末尾,就可以在不指定所有聚类键的情况下查询表?
在这种情况下,我不应该使用Map器吗?

5fjcxozz

5fjcxozz1#

如果您检查get-on-mapper的功能:
/**根据实体的主键获取实体

  • 这个方法基本上等价于:{@codemap(getManager().getSession().execute(getQuery(primaryKey)).one()}。

这意味着从数据库中获取Map类的单个实体,因此必须指定完整的主键。
正如我从您的示例中所理解的那样,您希望看到基于作业id和状态的作业运行列表,这些作业按last_run_at排序,这是范围查询。您可以创建Datastax accessor interface,添加范围查询并从代码中使用它。

@Accessor
public interface JobStatusAccessor {

    @Query("SELECT * FROM import_job_status WHERE job_id = :jobId AND "
        + "is_complete = :isComplete;")
    Statement getJobRunsByStatus(@Param("jobId") String jobId,
        @Param("isComplete") boolean isComplete);

}

与代码相比,您可以:

public JobStatus getIncompleteJobStatusById(String jobId)
{
        JobStatusAccessor jobStatusAccessor = new   MappingManager(_cassandraDatabaseManager.getSession()).createAccessor(JobStatusAccessor.class);

        boolean isComplete = false;
        List<JobStatus> jobRunsByStatus = jobStatusAccessor.getJobRunsByStatus(jobId, isComplete);

        return jobStatus.get(0); //here I suppose you need last one
}

通过查看您的模型,您可以存储首先按状态,然后按运行时间戳集群的作业运行列表。所以,当您提供作业id和状态时,您将得到作业运行列表,所以可能您的模型不正确(Map类的名称应该是e1d1e,而不是JobStatus)。如果您只需要作业运行的最后一个状态,则可以从集群键中删除lastRunAt,并执行upsert,这将只保留具有状态的最新运行,因此每个作业id和每个状态只有一个条目。

blmhpbnm

blmhpbnm2#

您面临此错误,因为您有多个分区键。
集群列是复合主键定义的一部分,但不是第一列。列聚集在单个分区内的多行中。聚类顺序由复合主键定义中列的位置决定。
作为驱动程序的官方java文档,解决方案是在分区键有多个组件时使用Ordinal int。
正确的配置可以是这样的:

@Table(keyspace = "storakle", name = "import_job_status")
public class JobStatus
{
    @PartitionKey(0)
    @Column(name = "job_id")
    private String jobId;   

    @ClusteringColumn(1)
    @Column(name = "is_complete")
    private boolean isComplete;

    @ClusteringColumn(2)
    @Column(name = "last_run_at")
    private Date lastRunAt;

    @Column(name = "run_number_of_times")
    private int runNumberOfTimes;
}
rqdpfwrv

rqdpfwrv3#

正如前面提到的答案,分区键和集群键上缺少序号。正确的配置是

@Table(keyspace = "storakle", name = "import_job_status")
public class JobStatus
{
  @PartitionKey(0)
  @Column(name = "job_id")
  private String jobId;   

  @ClusteringColumn(0)
  @Column(name = "is_complete")
  private boolean isComplete;

  @ClusteringColumn(1)
  @Column(name = "last_run_at")
  private Date lastRunAt;

  @Column(name = "run_number_of_times")
  private int runNumberOfTimes;
}

相关问题