AerospikeC客户端手册———聚合—记录聚合
记录聚合
有各种形式来处理次索引查询结果。一个常用的形式就是聚合,就是在整个查询结果集上应用一个函数。许多开发人员都熟知如何在数据库中使用SQL定义聚合查询。
例如,下面是一条从数据库中统计记录行数的SQL语句:
SELECT count(*)
FROM test.demo
WHERE d = 50
这条语句统计"test.demo"表中列"d"的值等于50的记录个数。
在Aerospike中,通过使用查询与用户定义函数来完成这个任务。
请先阅读:
【创建连接】章节,理解如何建立与集群的连接。
【次索引管理】章节,理解如何新创建次索引。
【查询】章节,理解如何使用C客户端实现查询。
定义查询
使用Aerospike C客户端API实现SQL语句相同的功能,可构建如下查询:
as_query query;
as_query_init(&query, "test", "demoset");
as_query_where_inita(&query, 1);
as_query_where(&query, "d", integer_equals(50));
as_query_apply(&query, "mymodule", "mycount", NULL);
上面的查询对象,被查找数据所在的namespace名称为“test”、set名称为“demoset”,在其中查找bin名是"d"且整型值等于50的记录。一个名字叫做”mycount()“的streamUDF将应用在查询结果集上,此streamUDF可在模块mymodule中找到。
注意:不带“where"语句的查询会导致全库扫描。
定义Stream UDF
定义Stream UDF
Stream UDF函数mycount()定义于模块mymodule,可以处理数据流。UDF mycont()定义是:
local function one(rec)
return 1
end
local function add(a, b)
return a + b
end
function mycount(stream)
return stream : map(one) : reduce(add);
end
函数mycount()是个Stream UDF,应用于流。在此案例中是查询结果流。我们在流上增加要在查询结果上执行的操作。在流上执行的操作是:
map — 从流中将一个值映射到另一个值。在这个示例中,映射被定义成函数one(),映射记录到数值1。
reduce — 从流中将多个值归纳成一个值。在这个示例中,归纳是将流中的两个值相加,.这些值就是来自映射函数的一堆数值1。
最终结果是一个包含单个值的流:count,或更技术化地讲,是结果集中每条记录对应的”1“的合计。
注册UDF
注册UDF
在一个查询能使用streamUDF之前,UDF函数必须注册到Aerospike服务器。
as_error err;
// Register the UDF file in the database cluster.
if (aerospike_udf_put(&as, &err, NULL, "mymodule", AS_UDF_TYPE_LUA,
&udf_content) != AEROSPIKE_OK) {
LOG("aerospike_udf_put() returned %d - %s", err.code, err.message);
}
执行查询
执行查询
使用aerospike_query_foreach()执行查询:
if (aerospike_query_foreach(&as, &err, NULL, &query, each_value, NULL) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}
这将在数据库中执行此查询。
处理结果
处理结果
对查询返回的值逐个调用函数each_value()。函数的实现可能类似于:
bool each_value(const as_val *val, void *udata) {
if (val == NULL) {
// query is complete
return true;
}
as_integer *ival = as_integer_fromval(val);
if (ival == NULL) {
// abort the query
return false;
}
// process the value
return true;
}
上面的示例中,返回1个整数,表明满足查询条件的记录计数。??????原文如此。
若想在每次回调时传递一个全局对象出来,请在调用aerospike_query_foreach()时提供一个userdata类型的参数。
清理资源
清理资源
一旦查询结束,查询对象与其成员对象可使用as_query_destroy()函数安全地释放。注意在我们的示例中,可以不用显式调用as_query_destroy(),因为是从栈上分配的as_query对象,并且使用了as_query_where_inita(),来避免内部使用堆。