【问题标题】:jq: Turn an array of objects into individual objects and use each array index as a new keyjq:将对象数组转换为单个对象,并使用每个数组索引作为新键
【发布时间】:2017-07-30 18:56:52
【问题描述】:

我有几个大型 json 对象(想想 GB 规模),其中一些最内层的对象值是对象数组。我正在使用 jq 1.4,我试图将这些数组分解为单独的对象,每个对象都有一个键,例如 g__0 或 g__1,其中数字对应于原始数组中的索引,由 @987654321 返回@ 功能。每个数组中的对象数量可以任意大(在我的示例中它等于 3)。同时我想保留剩余的结构。

原始结构来自 MongoDB,但我无法在此级别更改它。然后我将使用这个 json 文件为 BigQuery 创建一个架构,其中一个示例列将是 seeds.g__1.guid 等等。

我有什么:

{
 "port": 4500,
 "notes": "This is an example",
 "seeds": [
  {
    "seed": 12,
    "guid": "eaf612"
  },
  {
    "seed": 23,
    "guid": "bea143"
  },
  {
    "seed": 38,
    "guid": "efk311"
  }
  ]
}

我希望达到的目标:

{
  "port": 4500,
  "notes": "This is an example",
  "seeds": {
    "g__0": {
      "seed": 12,
      "guid": "eaf612"
    },
    "g__1": {
      "seed": 23,
      "guid": "bea143"
    },
    "g__2": {
      "seed": 38,
      "guid": "efk311"
    }
  }
}

谢谢!

【问题讨论】:

    标签: json google-bigquery jq


    【解决方案1】:

    下面的 jq 程序应该可以解决问题。至少它会为给定的 JSON 生成所需的结果。该程序非常简短明了,我将让它自己说话:

    def array2object(prefix):
      . as $in
      | reduce range(0;length) as $i ({}; .["\(prefix)_\($i)"] = $in[$i]);
    
    .seeds |= array2object("g__")
    

    【讨论】:

    • 感谢 peak,我在几个不同的场景中尝试了这个,它总是运行良好。
    【解决方案2】:

    因此,您实际上希望在 BigQuery 表中转置(透视)您的数据,而不是像下面那样将数据放在行中

    您的数据将显示在如下列中

    因此,我的建议是
    首先,按原样加载数据
    所以现在,与其在 BigQuery 之外进行架构转换,不如在 BigQuery 中进行!

    以下是如何实现您正在寻找的转换的示例(假设您在数组中最多有三个项目/对象)

    #standardSQL
    SELECT 
      port, notes, 
      STRUCT(
        seeds[SAFE_OFFSET(0)] AS g__0, 
        seeds[SAFE_OFFSET(1)] AS g__1, 
        seeds[SAFE_OFFSET(2)] AS g__2
      ) AS seeds 
    FROM yourTable   
    

    您可以使用 CTE 使用虚拟数据进行测试,如下所示

    #standardSQL
    WITH yourTable AS (
      SELECT 
        4500 AS port, 'This is an example' AS notes,
        [STRUCT<seed INT64, guid STRING>
            (12, 'eaf612'), (23, 'bea143'), (38, 'efk311')
        ] AS seeds
      UNION ALL SELECT 
        4501 AS port, 'This is an example 2' AS notes,
        [STRUCT<seed INT64, guid STRING>
            (42, 'eaf412'), (53, 'bea153')
        ] AS seeds
    )
    SELECT 
      port, notes, 
      STRUCT(
        seeds[SAFE_OFFSET(0)] AS g__0, 
        seeds[SAFE_OFFSET(1)] AS g__1, 
        seeds[SAFE_OFFSET(2)] AS g__2
      ) AS seeds 
    FROM yourTable   
    

    因此,从技术上讲,如果您知道种子数组中的最大项目/对象数 - 您可以手动编写所需的 SQL 语句,以针对真实数据运行它。
    希望你有想法

    当然,您可以编写/自动化流程 - 您可以在此处找到类似旋转任务的示例:

    https://stackoverflow.com/a/40766540/5221944
    https://stackoverflow.com/a/42287566/5221944

    【讨论】:

    • 非常感谢米哈伊尔的回复。我没有选择您的答案,因为在我的情况下,很难知道我的数组中的项目/对象的最大数量(而且我也有任意数量的此类数组),所以我发现操作行数据更可取。我同意这是 BigQuery 级别的好方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-07
    相关资源
    最近更新 更多