TANKENQI.cn

May 28, 2024

Postgres展平JSON(b)

database5.9 min to read

开发人员喜欢使用 JSON,当他们存储数据时,通常不会对其进行规范化。 因此,在数据库中遇到 JSON(b) 字段并不罕见。 对于数据分析师、数据科学家和机器学习工程师来说,取消嵌套或扁平化,数据往往是后续分析的先决条件。

整理数据库中的 JSON 列可能具有挑战性。 通常目标是将 JSON 数组扩展到新行并将 JSON 对象取消嵌套到新列中。 幸运的是,Postgres 有几个内置函数,可以组合这些函数来处理数据库中复杂 JSON 的规范化。

1 数据集

+---+-------------------+-------+---------------------------------+|idx|name               |country|coordinates                      |+---+-------------------+-------+---------------------------------+|1  |Sant Julià de Lòria|AD     |{"lat": 42.46372, "lng": 1.49129}||2  |Pas de la Casa     |AD     |{"lat": 42.54277, "lng": 1.73361}||3  |Ordino             |AD     |{"lat": 42.55623, "lng": 1.53319}||4  |les Escaldes       |AD     |{"lat": 42.50729, "lng": 1.53414}||5  |la Massana         |AD     |{"lat": 42.54499, "lng": 1.51483}||6  |Encamp             |AD     |{"lat": 42.53474, "lng": 1.58014}|+---+-------------------+-------+---------------------------------+

2 使用 jsonb_to_record 展平 JSON 对象

SELECT *FROM json_to_record('{"a":1,"b":[1,2,3],"c":"bar"}') AS  x(a int, b text, d text)
 a |    b    | d---+---------+--- 1 | [1,2,3] |
SELECT  city.idx,  city."name",  city.country,  coord.lat,  coord.lngFROM  city,  jsonb_to_record(coordinates) AS coord(lat numeric, lng numeric);
+---+-------------------+-------+--------+-------+|idx|name               |country|lat     |lng    |+---+-------------------+-------+--------+-------+|1  |Sant Julià de Lòria|AD     |42.46372|1.49129||2  |Pas de la Casa     |AD     |42.54277|1.73361||3  |Ordino             |AD     |42.55623|1.53319||4  |les Escaldes       |AD     |42.50729|1.53414||5  |la Massana         |AD     |42.54499|1.51483||6  |Encamp             |AD     |42.53474|1.58014|+---+-------------------+-------+--------+-------+

3 使用 jsonb_to_recordset 取消嵌套 JSON 数组

+---+------------+---------------------------------------------------------------+|idx|country_name|cities                                                         |+---+------------+---------------------------------------------------------------+|1  |AU          |[{"name": "York", "coordinates": {"lat": -31.88809, "lng": 1...||2  |AT          |[{"name": "Neu-Guntramsdorf", "coordinates": {"lat": 48.0642...||3  |AR          |[{"name": "Zárate", "coordinates": {"lat": -34.09814, "lng":...||4  |AG          |[{"name": "Saint John’s", "coordinates": {"lat": 17.12096, "...||5  |AO          |[{"name": "Saurimo", "coordinates": {"lat": -9.66078, "lng":...||6  |AQ          |[{"name": "McMurdo Station", "coordinates": {"lat": -77.846,...|+---+------------+---------------------------------------------------------------+
SELECT  idx,  country_name,  city.name,  city.coordinatesFROM country,     jsonb_to_recordset(cities) AS city(name text, coordinates jsonb);
+---+------------+---------+------------------------------------+|idx|country_name|name     |coordinates                         |+---+------------+---------+------------------------------------+|1  |AU          |York     |{"lat": -31.88809, "lng": 116.7678} ||1  |AU          |Yanchep  |{"lat": -31.54678, "lng": 115.63171}||1  |AU          |Yallingup|{"lat": -33.64592, "lng": 115.03514}||1  |AU          |Wundowie |{"lat": -31.76163, "lng": 116.3799} ||1  |AU          |Wooroloo |{"lat": -31.8038, "lng": 116.31311} ||1  |AU          |Woodville|{"lat": -34.88333, "lng": 138.55}   |+---+------------+---------+------------------------------------+

4 展平嵌套的 JSON

SELECT  idx,  country_name,  city.name,  coord.lat,  coord.lngFROM country,     jsonb_to_recordset(cities) AS city(name text, coordinates jsonb),     jsonb_to_record(coordinates) AS coord(lat numeric, lng numeric);
+---+------------+---------+---------+---------+|idx|country_name|name     |lat      |lng      |+---+------------+---------+---------+---------+|1  |AU          |York     |-31.88809|116.7678 ||1  |AU          |Yanchep  |-31.54678|115.63171||1  |AU          |Yallingup|-33.64592|115.03514||1  |AU          |Wundowie |-31.76163|116.3799 ||1  |AU          |Wooroloo |-31.8038 |116.31311||1  |AU          |Woodville|-34.88333|138.55   |+---+------------+---------+---------+---------+

5 结束语

在数据库中争论 JSON 的数据分析师、数据科学家和 ML 工程师可以使用 Postgres 的内置函数来规范化数据。 通过将这些函数组合在一起,可以将复杂的 JSON 扩展为新的行和列,以便它们可以在下游用于数据探索、数据分析和构建模型。


原文链接:Flattening JSON(b) in Postgres