Aerospike Stream使用实例

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}}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值