Cassandra group by和filter results

时间:2015-07-28 18:01:11

标签: group-by cassandra filtering user-defined-functions data-modeling

我试图模仿这样的事情: 给出一个表test

CREATE TABLE myspace.test (
item_id text,
sub_id text,
quantity bigint,
status text,
PRIMARY KEY (item_id, sub_id)

在SQL中,我们可以这样做:

select * from (select item_id, sum(quantity) as quan 
               from test where status <> 'somevalue') sub 
where sub.quan >= 10;

即。按item_id分组,然后用少于10的结果筛选出结果。

虽然我可以使用user-defined aggregate functions来模仿group by,但Cassandra不是为这类东西而设计的:

CREATE FUNCTION group_sum_state
   (state map<text, bigint>, item_id text, val bigint)
CALLED ON NULL INPUT
RETURNS map<text, bigint>
LANGUAGE java
AS $$Long current = (Long)state.get(item_id); 
if(current == null) current = 0l; 
state.put(item_id, current + val); return state;$$;

CREATE AGGREGATE group_sum(text, bigint)
SFUNC group_sum_state
STYPE map<text, bigint>
INITCOND {  }

并将其用作group by(可能这会有非常糟糕的表现,但仍然如此):

cqlsh:myspace> select group_sum(item_id, quantity) from test;

mysales_data.group_sum(item_id, quantity)
-------------------------------------------
     {'123': 33, '456': 14, '789': 15}

但似乎不可能通过映射值进行过滤,既不是聚合的最终函数也不是单独的函数。我可以定义一个这样的函数:

CREATE FUNCTION myspace.filter_group_sum
                (group map<text, bigint>, vallimit bigint)
CALLED ON NULL INPUT
RETURNS map<text, bigint>
LANGUAGE java
AS $$
java.util.Iterator<java.util.Map.Entry<String, Long>> entries = 
               group.entrySet().iterator(); 
while(entries.hasNext()) { 
    Long val = entries.next().getValue(); 
    if (val < vallimit) 
        entries.remove(); 
}; 
return group;$$;

但是没有办法调用它并传递一个常量:

select filter_group_sum(group_sum(item_id, quantity), 15) from test;
SyntaxException: <ErrorMessage code=2000 [Syntax error in CQL query] 
message="line 1:54 no viable alternative at input '15' 
(...(group_sum(item_id, quantity), [15]...)">

它抱怨常数15

很抱歉这篇长篇文章,我需要提供所有细节来解释我的需求。 所以我的问题是:

  1. 是否有办法将常量传递给Cassandra中的用户定义函数。或者我有什么替代方法来实现过滤组。
  2. 更一般的问题:Cassandra为实时查询服务应用程序覆盖这样一个用例的正确数据设计是什么?假设我有一个从UI获取限制的Web应用程序,需要返回总计quantity大于给定限制的所有项目?这些表格非常大,就像10亿条记录一样。

1 个答案:

答案 0 :(得分:3)

Vanilla Cassandra对于即席查询来说是一个糟糕的选择。 DataStax Enterprise通过与Spark和Solr的集成添加了一些此功能。 Spark集成也是开源的,但您不希望为低延迟查询执行此操作。如果您需要实时查询,则必须在Cassandra之外进行聚合(例如,在Spark或Storm中),然后回写您的应用程序要使用的聚合。您还可以查看Stratio的Lucene integration,它可能会帮助您解决一些问题。