列的注释@ClusteringColumn 的排序值无效?
Invalid ordering value for annotation @ClusteringColumn of column?
我正在使用 Cassandra 2.2.1。我有一个 table job_status 和以下键:
主键(job_id、is_complete、last_run_at)
WITH CLUSTERING ORDER BY (is_complete ASC, last_run_at DESC)
排序
我有以下 java class:
@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 class 查询我的 job_status table,如下所示:
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;
}
但是我收到以下错误:
"Invalid ordering value 0 for annotation @ClusteringColumn of column lastRunAt, was expecting 1"
我明白为什么会这样了。映射器获取在 JobStatus class 中注释的所有主键和集群键,并检查调用以获取 mapper.get 方法中提供的键是否与注释中的键的编号相同 class.
但我认为在 Cassandra 中可以查询 table 而无需指定所有聚类键,只要您省略的那些在最后?
在这种情况下我不应该使用 Mapper 吗?
如果你检查 get on mapper 做了什么:
/**
* Fetch an entity based on its primary key.
*
* This method is basically equivalent to: {@code map(getManager().getSession().execute(getQuery(primaryKey))).one()}.
这是为了从数据库中获取映射class的单个实体,因此必须指定完整的主键。
正如我从您的示例中了解到的那样,您希望根据 last_run_at
排序的作业 ID 和状态查看作业列表 运行,这是范围查询。您可以创建 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 和状态时,您将获得工作列表 运行,因此您的模型可能不正确(映射的名称 class 应该是 JobRun
,而不是 JobStatus
).如果您只需要作业 运行 的最后状态,您可以从集群键中删除 lastRunAt
并执行更新插入,这将只保留最新的 运行 状态,因此您将拥有每个作业 ID 和每个状态只有一个条目。
您遇到此错误是因为您有多个分区键。
集群列是复合主键定义的一部分,但不是第一列。
列聚集在单个分区内的多行中。聚簇顺序由列在复合主键定义中的位置决定。
作为驱动的官方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;
}
正如已经提到的答案,您缺少分区键和集群键的序号。
正确的配置是
@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;
}
我正在使用 Cassandra 2.2.1。我有一个 table job_status 和以下键:
主键(job_id、is_complete、last_run_at) WITH CLUSTERING ORDER BY (is_complete ASC, last_run_at DESC)
排序我有以下 java class:
@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 class 查询我的 job_status table,如下所示:
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;
}
但是我收到以下错误:
"Invalid ordering value 0 for annotation @ClusteringColumn of column lastRunAt, was expecting 1"
我明白为什么会这样了。映射器获取在 JobStatus class 中注释的所有主键和集群键,并检查调用以获取 mapper.get 方法中提供的键是否与注释中的键的编号相同 class.
但我认为在 Cassandra 中可以查询 table 而无需指定所有聚类键,只要您省略的那些在最后?
在这种情况下我不应该使用 Mapper 吗?
如果你检查 get on mapper 做了什么:
/** * Fetch an entity based on its primary key. *
* This method is basically equivalent to: {@code map(getManager().getSession().execute(getQuery(primaryKey))).one()}.
这是为了从数据库中获取映射class的单个实体,因此必须指定完整的主键。
正如我从您的示例中了解到的那样,您希望根据 last_run_at
排序的作业 ID 和状态查看作业列表 运行,这是范围查询。您可以创建 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 和状态时,您将获得工作列表 运行,因此您的模型可能不正确(映射的名称 class 应该是 JobRun
,而不是 JobStatus
).如果您只需要作业 运行 的最后状态,您可以从集群键中删除 lastRunAt
并执行更新插入,这将只保留最新的 运行 状态,因此您将拥有每个作业 ID 和每个状态只有一个条目。
您遇到此错误是因为您有多个分区键。
集群列是复合主键定义的一部分,但不是第一列。 列聚集在单个分区内的多行中。聚簇顺序由列在复合主键定义中的位置决定。
作为驱动的官方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;
}
正如已经提到的答案,您缺少分区键和集群键的序号。 正确的配置是
@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;
}