如何通过条件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

Test

.backup | map( select( .type == "full" ).timestamp.stop ) | max

Test

借助通用的辅助函数进行计数,这里有一个完整的解决方案,假设您想根据 .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 所要求的。