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函數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
在一個查詢能使用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(),來避免內部使用堆。