You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JQ将ElasticSearch JSON输出为缺失值补0的表格

Got it, let's work through this. You've already got a line-by-line output (asset + date + value) from jq + sed, and now you want to pivot that into a clean table where dates are columns, assets are rows, and missing date-asset pairs get filled with 0. I'll cover two approaches: directly generating the table from your ElasticSearch aggregation response (more efficient, no sed needed), and post-processing your existing line output.

Approach 1: Directly from ElasticSearch Aggregation Response

First, let's assume your ES aggregation response looks something like this (adjust field names if yours differ):

{
  "aggregations": {
    "assets": {
      "buckets": [
        {
          "key": "asset_001",
          "date_buckets": {
            "buckets": [
              {
                "key_as_string": "2024-05-01",
                "totalMaxUptime": { "value": 100 }
              },
              {
                "key_as_string": "2024-05-03",
                "totalMaxUptime": { "value": 95 }
              }
            ]
          }
        },
        {
          "key": "asset_002",
          "date_buckets": {
            "buckets": [
              {
                "key_as_string": "2024-05-01",
                "totalMaxUptime": { "value": 98 }
              },
              {
                "key_as_string": "2024-05-02",
                "totalMaxUptime": { "value": 100 }
              }
            ]
          }
        }
      ]
    }
  }
}

Use this jq command to generate a Markdown table directly:

(
  # Collect and sort all unique dates
  [.aggregations.assets.buckets[].date_buckets.buckets[].key_as_string] | unique | sort as $dates
)
(
  # Collect all unique assets
  [.aggregations.assets.buckets[].key] | unique as $assets
)
# Build a map for each asset: date -> value (0 if missing)
| .aggregations.assets.buckets | map(
  .key as $asset
  | reduce .date_buckets.buckets[] as $b ({}; .[$b.key_as_string] = $b.totalMaxUptime.value)
  | { asset: $asset, values: $dates | map(.[.] // 0) }
) as $rows
# Generate Markdown table structure
| "| Asset ID |" + ($dates | map(" " + . + " |") | join(""))
, "|-----------|" + ($dates | map("---------|") | join(""))
, ($rows | map("| " + .asset + " |" + (.values | map(" " + tostring + " |") | join(""))) | .[])

If you prefer CSV instead (easier for spreadsheets), use this variant:

(
  [.aggregations.assets.buckets[].date_buckets.buckets[].key_as_string] | unique | sort as $dates
)
(
  [.aggregations.assets.buckets[].key] | unique as $assets
)
| .aggregations.assets.buckets | map(
  .key as $asset
  | reduce .date_buckets.buckets[] as $b ({}; .[$b.key_as_string] = $b.totalMaxUptime.value)
  | { asset: $asset, values: $dates | map(.[.] // 0) }
) as $rows
| "Asset ID," + ($dates | join(","))
, ($rows | map(.asset + "," + (.values | join(","))) | .[])

Approach 2: Post-Process Your Existing Line Output

If you already have a file (let's call it asset_data.txt) with lines like:

asset_001 2024-05-01 100
asset_001 2024-05-03 95
asset_002 2024-05-01 98
asset_002 2024-05-02 100

Use this awk script (pivot_to_table.awk) to convert it to a Markdown table:

BEGIN {
  # Read all data into a 2D map: asset -> date -> value
  while (getline < "asset_data.txt") {
    data[$1][$2] = $3
    all_dates[$2] = 1
    all_assets[$1] = 1
  }

  # Sort dates and assets alphabetically
  sort_array(all_dates, sorted_dates)
  sort_array(all_assets, sorted_assets)

  # Print Markdown header
  printf "| Asset ID |"
  for (i in sorted_dates) printf " %s |", sorted_dates[i]
  printf "\n|-----------|"
  for (i in sorted_dates) printf "---------|"
  printf "\n"

  # Print each asset's row
  for (a in sorted_assets) {
    asset = sorted_assets[a]
    printf "| %s |", asset
    for (d in sorted_dates) {
      date = sorted_dates[d]
      printf " %s |", data[asset][date] ? data[asset][date] : 0
    }
    printf "\n"
  }
}

# Helper function to sort an associative array into an indexed array
sort_array(input_arr, output_arr) {
  idx = 1
  for (item in input_arr) output_arr[idx++] = item
  n = idx - 1
  for (i=1; i<n; i++) {
    for (j=i+1; j<=n; j++) {
      if (output_arr[i] > output_arr[j]) {
        temp = output_arr[i]
        output_arr[i] = output_arr[j]
        output_arr[j] = temp
      }
    }
  }
}

Run it with:

awk -f pivot_to_table.awk

Both approaches will give you a table like this:

Asset ID2024-05-012024-05-022024-05-03
asset_001100095
asset_002981000

Just make sure to adjust field names (like date_buckets if your aggregation has a different name) to match your actual ES response.

内容的提问来源于stack exchange,提问作者am1991

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:36:07