如何基于指定key对对象/数组去重,用jq按.hash去重后统计时间范围内金额总和
问题描述
存在重复JSON payload数据时,如何按指定字段去重后统计指定时间段内的amount总和,具体场景如下:
现有多段存在重复的JSON payload,格式如下:
{ "data": [ { "account": "12xUoMKwf12ABjNx4VCvYcNkX79gW1kzz2JnBLxkFbjswRczRvM", "amount": 7885016, "block": 470788, "gateway": "113kQU96zqePySTahB7PEde9ZpoWK76DYK1f57wyhjhXCBoAu88", "hash": "DTU1GGfR0eU15hv6KiV_bg6FOJXfUWz4TjIq1H7TGy4", "timestamp": "2020-08-28T01:29:46.000000Z" } ] } { "data": [ { "account": "12xUoMKwf12ABjNx4VCvYcNkX79gW1kzz2JnBLxkFbjswRczRvM", "amount": 7885016, "block": 470788, "gateway": "113kQU96zqePySTahB7PEde9ZpoWK76DYK1f57wyhjhXCBoAu88", "hash": "DTU1GGfR0eU15hv6KiV_bg6FOJXfUWz4TjIq1H7TGy4", "timestamp": "2020-08-28T01:29:46.000000Z" } ] } { "data": [ { "account": "12xUoMKwf12ABjNx4VCvYcNkX79gW1kzz2JnBLxkFbjswRczRvM", "amount": 8623955, "block": 470509, "gateway": "113kQU96zqePySTahB7PEde9ZpoWK76DYK1f57wyhjhXCBoAu88", "hash": "5fQJY9MprH9b3IstVU1SdfBteUWoF_sdsVuiARPBtTY", "timestamp": "2020-08-27T19:01:48.000000Z" } ] }
其中前两段payload完全重复,要求按hash字段去重后,统计符合指定时间段的amount总和。现有可提取时间范围内amount的jq代码,但未做去重:
jq --arg this "$(date +%Y-%m-%dT%H:%M:%S)" '.data[] | select(.timestamp >= $this) | .amount'
解决方案
你可以用reduce把所有数据按hash存入临时对象实现去重,再过滤时间范围后求和,具体代码如下:
jq -s --arg this "$(date +%Y-%m-%dT%H:%M:%S)" ' reduce .[].data[] as $item ({}; .[$item.hash] = $item) | .[] | select(.timestamp >= $this) | .amount ' | paste -sd+ - | bc
如果希望直接在jq内部完成求和,不需要后续管道处理,可以使用下面的写法:
jq -s --arg this "$(date +%Y-%m-%dT%H:%M:%S)" ' reduce .[].data[] as $item ({}; .[$item.hash] = $item) | [.[] | select(.timestamp >= $this).amount] | add '
代码说明
-s参数:将输入的多个独立JSON对象读入为一个数组,方便统一处理reduce逻辑:遍历所有条目,以hash为键存入对象,重复hash会覆盖之前的取值,自动实现去重- 最后将去重后符合时间要求的
amount累加得到最终结果
内容的提问来源于stack exchange,提问作者Nick Hatfield
相关产品推荐
相关产品推荐

