Aerospike Stream使用实例
求解目标
计算5分钟内,用户的平均交易额
数据模型
- userId – 用户唯一标识
- amount – 交易金额
- tradeTime – 交易时间
- city --交易城市
代码
Lua脚本
--[[
以userId为维度,聚合某个节点某个数据分区的数据
users--存储数据分区所有用户的交易情况的大map
record--某一条交易记录
]]
local function groupByUserId(users, record)
local userId = record.userId;
local user = users[userId] or map { userId = userId, count = 0, amount = 0, average = 0 }
local count = user.count
count = count + 1;
user.count = count
local recordAmount = record.amount
local flag = not (recordAmount == nil);
local amount = user.amount
if flag then
user.amount = amount + recordAmount
end
users[userId] = user
return users
end
--[[
合并各个节点各个数据分区的统计数据
current--当前数据分区统计map
another--其他数据分区统计map
]]
local function reduceByUserId(current, another)
local function mergeByUserId(firstMap, secondMap)
local count = firstMap['count'] + secondMap['count'];
local amount = firstMap['amount'] + secondMap['amount'];
local average = 0;
local flag = not (count == 0)
if flag then
average = amount / count
end
return map { count = count, amount = amount, average = average, userId = firstMap['userId'] }
end
return map.merge(current, another, mergeByUserId)
end
--[[
以userId为维度计算平均值
stream--根据查询二级索引获得的记录流
]]
function calAverage(stream)
return stream:aggregate(map(), groupByUserId):reduce(reduceByUserId)
end
Java客户端
private static void average5min() {
AerospikeClient client = multiClient();
List<Key> keys = new ArrayList<>();
//生成随机数据
int limit = 200;
for (int i = 0; i < limit; i++) {
Key key = new Key("test", "trade", i);
keys.add(key);
Bin[] bins = getBins(i);
client.put(null, key, bins);
}
//打印看下到底是个生成了什么数据
for (Key key : keys) {
Record record = client.get(null, key);
System.out.println(record.bins);
}
//准备二级索引
prepareIndex(client, "test", "trade", "index-average5min", "tradeTime");
//注册UDF
registerUDF(RESOURCE_DIR + "/udf/average5min.lua", "average5min.lua");
//创建查询对象
Statement statement = new Statement();
statement.setNamespace("test");
statement.setSetName("trade");
long millis = System.currentTimeMillis();
long start = millis - 5 * 60 * 1000;
System.out.println(String.format("start:%s,end:%s", start, millis));
statement.setFilter(Filter.range("tradeTime", start, millis));
//看一看是否真的存在了
System.out.println("-----------query---------------");
try (RecordSet query = client.query(null, statement);) {
while (query.next()) {
System.out.println(query.getRecord().bins);
}
}
LuaConfig.SourceDirectory = RESOURCE_DIR + "/udf";
//调用stream udf
try (ResultSet resultSet = client.queryAggregate(null, statement, "average5min", "calAverage")) {
System.out.println("--------agg using udf--------");
while (resultSet.next()) {
System.out.println(resultSet.getObject());
}
}
close(client);
}
private static void prepareIndex(AerospikeClient client, String namespace, String setName, String indexName, String indexField, IndexType indexType) {
try {
IndexTask task = client.createIndex(null, namespace, setName, indexName, indexField, indexType);
task.waitTillComplete();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取bin对象
*
* @param index 下标
* @return bin对象数组
*/
private static Bin[] getBins(int index) {
int num = random.nextInt(20) + 1;
return new Bin[]{
new Bin("userId", "userId" + index % num),
new Bin("amount", random.nextInt(600)),
new Bin("city", "city" + index % 10),
//让交易时间随机一下
new Bin("tradeTime", getDateTimeIn(Calendar.MINUTE, 5)),
};
}
输出
{userId8={count=13, average=321.46153846153845, amount=4179, userId=userId8}, userId9={count=10, average=307.5, amount=3075, userId=userId9}, userId6={count=12, average=286.75, amount=3441, userId=userId6}, userId7={count=11, average=197.36363636363637, amount=2171, userId=userId7}, userId13={count=5, average=151.4, amount=757, userId=userId13}, userId0={count=29, average=249.9655172413793, amount=7249, userId=userId0}, userId14={count=2, average=293.5, amount=587, userId=userId14}, userId1={count=20, average=268.8, amount=5376, userId=userId1}, userId15={count=2, average=370.5, amount=741, userId=userId15}, userId16={count=1, average=0, amount=248, userId=userId16}, userId4={count=19, average=263.05263157894734, amount=4998, userId=userId4}, userId17={count=1, average=0, amount=514, userId=userId17}, userId5={count=11, average=382.8181818181818, amount=4211, userId=userId5}, userId19={count=1, average=0, amount=235, userId=userId19}, userId2={count=25, average=282.6, amount=7065, userId=userId2}, userId3={count=17, average=314.88235294117646, amount=5353, userId=userId3}, userId10={count=11, average=392.8181818181818, amount=4321, userId=userId10}, userId11={count=6, average=200.16666666666666, amount=1201, userId=userId11}, userId12={count=4, average=285.25, amount=1141, userId=userId12}}