通过 cqlsh 请求对 Cassandra 执行减法的最佳方法是什么?
What is the best way to perform a subtraction on Cassandra by cqlsh request?
我正在尝试在 Cassandra 上发出 cqlsh 请求。这个想法是分析在基因组中注释的不同 'gene' 寄存器的平均长度。输入数据后,我有这个 athaliana.tab table:
id | chr | comments | end | orf | sense | start | type
--------------------------------------+-----+-------------------+----------+-----+-------+----------+------
d2ab2520-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G16340 | 5590338 | 0 | - | 5590241 | CDS
d4169c00-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G16610 | 5676495 | . | - | 5676429 | exon
a8c792c0-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G07485 | 2301889 | 0 | + | 2301665 | CDS
3bd5c0a0-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G51980 | 19326916 | . | - | 19326733 | exon
263b5b60-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G44990 | 17007808 | . | - | 17007542 | gene
67989a50-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G63110 | 23405144 | . | + | 23404821 | UTR
26f7f4a0-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G45180 | 17101207 | 0 | + | 17101109 | CDS
3743dc70-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G50840 | 18841644 | 0 | + | 18840965 | CDS
e5099940-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G20620 | 7145780 | . | + | 7145691 | exon
2ba30620-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G48180 | 17793717 | . | - | 17792449 | gene
思路是获取end-start列数据之间的差值并计算平均值。我试过这种方式:
SELECT avg(end-start) FROM athaliana.tab WHERE chr = '1' AND type = 'gene';
但结果是:
SyntaxException: <ErrorMessage code=2000 [Syntax error in CQL query] message="line 1:14 no viable alternative at input '-' (SELECT avg([end]-...)">
一些想法?非常感谢任何帮助。
Cassandra 专为最大读写效率而设计,不内置支持应用于多列的函数,例如 plus
或 minus
,也不支持 聚合 ,即应用于多行的函数,例如 avg
或 count
.
直到最近,解决方法是将函数的结果存储在单独的列中,并在您自己的应用程序代码中执行聚合。
但是,Cassandra 2.2 和 3.0 现在提供用户定义的函数(UDF)和用户定义的聚合(UDA)。您现在可以定义自己的函数,然后让 Cassandra 为您调用它们。请参阅 UDFs and UDAs or this blog post 上的 CQL 规范章节。
首先,创建以下函数和聚合:
USE athaliana;
CREATE FUNCTION minus (x int, y int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE java AS 'return x-y;';
CREATE FUNCTION avgState (state tuple<int,bigint>, val int) CALLED ON NULL INPUT RETURNS tuple<int,bigint> LANGUAGE java AS '
if (val != null) {
state.setInt(0, state.getInt(0)+1);
state.setLong(1, state.getLong(1)+val.intValue());
}
return state;
';
CREATE FUNCTION avgFinal (state tuple<int,bigint>) CALLED ON NULL INPUT RETURNS double LANGUAGE java AS '
double r = 0;
if (state.getInt(0) == 0) return null;
r = state.getLong(1);
r /= state.getInt(0);
return Double.valueOf(r);
';
CREATE AGGREGATE avg(int) SFUNC avgState STYPE tuple<int,bigint> FINALFUNC avgFinal INITCOND (0, 0);
那么您的查询可以这样重写:
SELECT avg(minus(end,start)) FROM athaliana.tab WHERE chr = '1' AND type = 'gene';
请注意,您应该只对单个分区键使用聚合;如果不是这种情况,将发出警告。
我正在尝试在 Cassandra 上发出 cqlsh 请求。这个想法是分析在基因组中注释的不同 'gene' 寄存器的平均长度。输入数据后,我有这个 athaliana.tab table:
id | chr | comments | end | orf | sense | start | type
--------------------------------------+-----+-------------------+----------+-----+-------+----------+------
d2ab2520-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G16340 | 5590338 | 0 | - | 5590241 | CDS
d4169c00-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G16610 | 5676495 | . | - | 5676429 | exon
a8c792c0-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G07485 | 2301889 | 0 | + | 2301665 | CDS
3bd5c0a0-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G51980 | 19326916 | . | - | 19326733 | exon
263b5b60-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G44990 | 17007808 | . | - | 17007542 | gene
67989a50-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G63110 | 23405144 | . | + | 23404821 | UTR
26f7f4a0-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G45180 | 17101207 | 0 | + | 17101109 | CDS
3743dc70-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G50840 | 18841644 | 0 | + | 18840965 | CDS
e5099940-6734-11e5-955c-234085c1edec | 1 | gene_id AT1G20620 | 7145780 | . | + | 7145691 | exon
2ba30620-6735-11e5-955c-234085c1edec | 1 | gene_id AT1G48180 | 17793717 | . | - | 17792449 | gene
思路是获取end-start列数据之间的差值并计算平均值。我试过这种方式:
SELECT avg(end-start) FROM athaliana.tab WHERE chr = '1' AND type = 'gene';
但结果是:
SyntaxException: <ErrorMessage code=2000 [Syntax error in CQL query] message="line 1:14 no viable alternative at input '-' (SELECT avg([end]-...)">
一些想法?非常感谢任何帮助。
Cassandra 专为最大读写效率而设计,不内置支持应用于多列的函数,例如 plus
或 minus
,也不支持 聚合 ,即应用于多行的函数,例如 avg
或 count
.
直到最近,解决方法是将函数的结果存储在单独的列中,并在您自己的应用程序代码中执行聚合。
但是,Cassandra 2.2 和 3.0 现在提供用户定义的函数(UDF)和用户定义的聚合(UDA)。您现在可以定义自己的函数,然后让 Cassandra 为您调用它们。请参阅 UDFs and UDAs or this blog post 上的 CQL 规范章节。
首先,创建以下函数和聚合:
USE athaliana;
CREATE FUNCTION minus (x int, y int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE java AS 'return x-y;';
CREATE FUNCTION avgState (state tuple<int,bigint>, val int) CALLED ON NULL INPUT RETURNS tuple<int,bigint> LANGUAGE java AS '
if (val != null) {
state.setInt(0, state.getInt(0)+1);
state.setLong(1, state.getLong(1)+val.intValue());
}
return state;
';
CREATE FUNCTION avgFinal (state tuple<int,bigint>) CALLED ON NULL INPUT RETURNS double LANGUAGE java AS '
double r = 0;
if (state.getInt(0) == 0) return null;
r = state.getLong(1);
r /= state.getInt(0);
return Double.valueOf(r);
';
CREATE AGGREGATE avg(int) SFUNC avgState STYPE tuple<int,bigint> FINALFUNC avgFinal INITCOND (0, 0);
那么您的查询可以这样重写:
SELECT avg(minus(end,start)) FROM athaliana.tab WHERE chr = '1' AND type = 'gene';
请注意,您应该只对单个分区键使用聚合;如果不是这种情况,将发出警告。