如何通过条件select最大值然后与其他值进行比较?
How to select max value by condition and then compare it with others?
我有一个 json 描述的备份集。示例如下。
我想计算自上次完整备份以来添加了多少增量备份。
我尝试 select 类型为“full”的记录的最大时间戳,所以之后我将计算有多少类型为“incr”的记录具有更大的时间戳。
{
"archive": [
{
"database": {
"id": 1
},
"id": "11-1",
"max": "0000000A000018B90000006A",
"min": "0000000A0000167D000000C7"
}
],
"backup": [
{
"archive": {
"start": "0000000A0000181600000030",
"stop": "0000000A0000181C00000083"
},
"backrest": {
"format": 5,
"version": "2.28"
},
"database": {
"id": 1
},
"info": {
"delta": 417875448942,
"repository": {
"delta": 67466720725,
"size": 67466720725
},
"size": 417875448942
},
"label": "20201213-200009F",
"prior": null,
"reference": null,
"timestamp": {
"start": 1607878809,
"stop": 1607896232
},
"type": "full"
},
{
"archive": {
"start": "0000000A0000182900000065",
"stop": "0000000A0000182F00000069"
},
"backrest": {
"format": 5,
"version": "2.28"
},
"database": {
"id": 1
},
"info": {
"delta": 122520170241,
"repository": {
"delta": 19316550760,
"size": 67786280115
},
"size": 416998156028
},
"label": "20201213-200009F_20201214-200009I",
"prior": "20201213-200009F",
"reference": [
"20201213-200009F"
],
"timestamp": {
"start": 1607965209,
"stop": 1607974161
},
"type": "incr"
},
{
"archive": {
"start": "0000000A0000185B000000DD",
"stop": "0000000A0000185B000000F4"
},
"backrest": {
"format": 5,
"version": "2.28"
},
"database": {
"id": 1
},
"info": {
"delta": 126982395984,
"repository": {
"delta": 19541379733,
"size": 67993072945
},
"size": 421395153101
},
"label": "20201213-200009F_20201217-200105I",
"prior": "20201213-200009F_20201214-200009I",
"reference": [
"20201213-200009F",
"20201213-200009F_20201214-200009I"
],
"timestamp": {
"start": 1608224465,
"stop": 1608233408
},
"type": "incr"
}
]
}
我试图通过此命令完成第一部分,但它说“数字 (1607896232) 和数字 (1607896232) 无法迭代”
.[0] |.backup[] | select(.type=="full").timestamp.stop|max
我尝试了 sort_by 但没有成功。那么我在这里做错了什么?
max
需要一个数组。
[ .backup[] | select( .type == "full" ).timestamp.stop ] | max
或
.backup | map( select( .type == "full" ).timestamp.stop ) | max
借助通用的辅助函数进行计数,这里有一个完整的解决方案,假设您想根据 .timestamp.start
:
进行计数
def count(s): reduce s as $x (0; .+1);
.backup
| (map( select( .type == "full" ).timestamp.stop) | max) as $max
| count(.[] | select( .type == "incr" and .timestamp.start > $max))
使用max/1
对于大型阵列,使用 max
的流式版本可能会更有效:
def count(s): reduce s as $x (0; .+1);
# Note: max(empty) #=> null
def max(s):
reduce s as $s (null; if $s > .m then $s else . end);
.backup
| max(.[] | select( .type == "full" ).timestamp.stop) as $max
| count(.[] | select( .type == "incr" and .timestamp.start > $max))
所以,在我解决了获取具体值的问题之后(感谢@ikegami),我通过这种方式解决了我的整个问题
jq '(.[0] |[.backup[] | select(.type=="full").timestamp.stop]|max) as $i| [.[0] |.backup[] | select(.type=="incr" and .timestamp.stop>$i)]|length
不确定它是否优化,但它仍然有效。
这里还有一个替代(非 jq)解决方案,如何使用 jtc
工具实现相同的 JSON 查询:
bash $ <input.json jtc -jw'[timestamp]:<>G:[-1][type]' / -w'<full><>k'
2
PS。我是 jtc
unix JSON 处理器
的开发者
PPS。以上免责声明是 SO 所要求的。
我有一个 json 描述的备份集。示例如下。 我想计算自上次完整备份以来添加了多少增量备份。 我尝试 select 类型为“full”的记录的最大时间戳,所以之后我将计算有多少类型为“incr”的记录具有更大的时间戳。
{
"archive": [
{
"database": {
"id": 1
},
"id": "11-1",
"max": "0000000A000018B90000006A",
"min": "0000000A0000167D000000C7"
}
],
"backup": [
{
"archive": {
"start": "0000000A0000181600000030",
"stop": "0000000A0000181C00000083"
},
"backrest": {
"format": 5,
"version": "2.28"
},
"database": {
"id": 1
},
"info": {
"delta": 417875448942,
"repository": {
"delta": 67466720725,
"size": 67466720725
},
"size": 417875448942
},
"label": "20201213-200009F",
"prior": null,
"reference": null,
"timestamp": {
"start": 1607878809,
"stop": 1607896232
},
"type": "full"
},
{
"archive": {
"start": "0000000A0000182900000065",
"stop": "0000000A0000182F00000069"
},
"backrest": {
"format": 5,
"version": "2.28"
},
"database": {
"id": 1
},
"info": {
"delta": 122520170241,
"repository": {
"delta": 19316550760,
"size": 67786280115
},
"size": 416998156028
},
"label": "20201213-200009F_20201214-200009I",
"prior": "20201213-200009F",
"reference": [
"20201213-200009F"
],
"timestamp": {
"start": 1607965209,
"stop": 1607974161
},
"type": "incr"
},
{
"archive": {
"start": "0000000A0000185B000000DD",
"stop": "0000000A0000185B000000F4"
},
"backrest": {
"format": 5,
"version": "2.28"
},
"database": {
"id": 1
},
"info": {
"delta": 126982395984,
"repository": {
"delta": 19541379733,
"size": 67993072945
},
"size": 421395153101
},
"label": "20201213-200009F_20201217-200105I",
"prior": "20201213-200009F_20201214-200009I",
"reference": [
"20201213-200009F",
"20201213-200009F_20201214-200009I"
],
"timestamp": {
"start": 1608224465,
"stop": 1608233408
},
"type": "incr"
}
]
}
我试图通过此命令完成第一部分,但它说“数字 (1607896232) 和数字 (1607896232) 无法迭代”
.[0] |.backup[] | select(.type=="full").timestamp.stop|max
我尝试了 sort_by 但没有成功。那么我在这里做错了什么?
max
需要一个数组。
[ .backup[] | select( .type == "full" ).timestamp.stop ] | max
或
.backup | map( select( .type == "full" ).timestamp.stop ) | max
借助通用的辅助函数进行计数,这里有一个完整的解决方案,假设您想根据 .timestamp.start
:
def count(s): reduce s as $x (0; .+1);
.backup
| (map( select( .type == "full" ).timestamp.stop) | max) as $max
| count(.[] | select( .type == "incr" and .timestamp.start > $max))
使用max/1
对于大型阵列,使用 max
的流式版本可能会更有效:
def count(s): reduce s as $x (0; .+1);
# Note: max(empty) #=> null
def max(s):
reduce s as $s (null; if $s > .m then $s else . end);
.backup
| max(.[] | select( .type == "full" ).timestamp.stop) as $max
| count(.[] | select( .type == "incr" and .timestamp.start > $max))
所以,在我解决了获取具体值的问题之后(感谢@ikegami),我通过这种方式解决了我的整个问题
jq '(.[0] |[.backup[] | select(.type=="full").timestamp.stop]|max) as $i| [.[0] |.backup[] | select(.type=="incr" and .timestamp.stop>$i)]|length
不确定它是否优化,但它仍然有效。
这里还有一个替代(非 jq)解决方案,如何使用 jtc
工具实现相同的 JSON 查询:
bash $ <input.json jtc -jw'[timestamp]:<>G:[-1][type]' / -w'<full><>k'
2
PS。我是 jtc
unix JSON 处理器
的开发者
PPS。以上免责声明是 SO 所要求的。