【问题标题】:Postgres - query json with nested arrray and objects inside arrayPostgres - 使用嵌套数组和数组内的对象查询 json
【发布时间】:2021-12-10 20:01:59
【问题描述】:

我将数据作为 jsonb 存储在 Postgres 12 表中,jsonb 的结构在数组内部有一个数组。

如何从嵌套数组中获取值?我可以从一级数组中获取值,但不能从二级数组中获取值。

这是一个简化的json示例

{
    "id": 1,
    "external_order_id": {
        "id": "2"
    },
    "customer": {
        "external_customer_id": {
            "id": "3"
        }
    },
    "line_items": [
        {
            "sku": "SKU-1",
            "properties": [
                {
                    "name": "colour",
                    "value": "red"
                },
                {
                    "name": "size",
                    "value": "large"
                }
            ],
            "external_product_id": {
                "id": "4"
            },
            "external_variant_id": {
                "id": "5"
            }
        },
        {
            "sku": "SKU-2",
            "properties": [
                {
                    "name": "colour",
                    "value": "black"
                },
                {
                    "name": "size",
                    "value": "small"
                }
            ],
            "external_product_id": {
                "id": "8"
            },
            "external_variant_id": {
                "id": "9"
            }
        }
    ]
}

将 jsonb_to_record 和 jsonb_to_recordset 与 LATERAL 和 CROSS JOIN LATERAL 一起使用,我能够从节点和第一级数组中获取值

WITH data(content) AS ( VALUES
  ('{
    "id": 1,
         "external_order_id": {
        "id": "2"
    },
    "customer": {
        
        "external_customer_id": {
            "id": "3"
        }
    },
    "line_items": [
        {
            "sku": "SKU-1",
            "properties": [
                {
                    "name": "colour",
                    "value": "red"
                },
                {
                    "name": "size",
                    "value": "large"
                }
            ],
            "external_product_id": {
                "id": "4"
            },
            "external_variant_id": {
                "id": "5"
            }
        },
                {
            "sku": "SKU-2",
            "properties": [
                {
                    "name": "colour",
                    "value": "black"
                },
                {
                    "name": "size",
                    "value": "small"
                }
            ],
            "external_product_id": {
                "id": "8"
            },
            "external_variant_id": {
                "id": "9"
            }
        }
    ]
   
}'::jsonb)
)
select ord.*
,ext.id as external_order_id
,cus.id as external_customer_id
,line_items.*

FROM data,
jsonb_to_record(content) as ord(id int),
LATERAL jsonb_to_record(content->'external_order_id') as ext(id text),
LATERAL jsonb_to_record(content#>'{customer, external_customer_id}') as cus(id text)
CROSS JOIN LATERAL jsonb_to_recordset(content->'line_items') line_items(sku text)

这是目前的结果

| id | external_order_id | external_customer_id | sku   |
|----|-------------------|----------------------|-------|
| 1  | 2                 | 3                    | SKU-1 |
| 1  | 2                 | 3                    | SKU-2 |

我想要实现的是。 理想情况下,这将在不知道属性名称的值的情况下实现

| id | external_order_id | external_customer_id | sku   | external_product_id | external_variant_id | property_name | property_value |
|----|-------------------|----------------------|-------|---------------------|---------------------|---------------|----------------|
| 1  | 2                 | 3                    | SKU-1 | 4                   | 5                   | colour        | red            |
| 1  | 2                 | 3                    | SKU-1 | 4                   | 5                   | size          | large          |
| 1  | 2                 | 3                    | SKU-2 | 8                   | 9                   | colour        | black          |
| 1  | 2                 | 3                    | SKU-2 | 8                   | 9                   | size          | small          |

dbfiddle

【问题讨论】:

    标签: postgresql postgres-12


    【解决方案1】:
    WITH data(content) AS ( VALUES
      ('{
        "id": 1,
             "external_order_id": {
            "id": "2"
        },
        "customer": {
    
            "external_customer_id": {
                "id": "3"
            }
        },
        "line_items": [
            {
                "sku": "SKU-1",
                "properties": [
                    {
                        "name": "colour",
                        "value": "red"
                    },
                    {
                        "name": "size",
                        "value": "large"
                    }
                ],
                "external_product_id": {
                    "id": "4"
                },
                "external_variant_id": {
                    "id": "5"
                }
            },
                    {
                "sku": "SKU-2",
                "properties": [
                    {
                        "name": "colour",
                        "value": "black"
                    },
                    {
                        "name": "size",
                        "value": "small"
                    }
                ],
                "external_product_id": {
                    "id": "8"
                },
                "external_variant_id": {
                    "id": "9"
                }
            }
        ]
    
    }'::jsonb)
    )
    select ord.*
    ,ext.id as external_order_id
    ,cus.id as external_customer_id
    ,line_items.sku
    ,line_items.external_product_id->>'id' as external_product_id
    ,line_items.external_variant_id->>'id' as external_variant_id
    ,props.*
    FROM data,
    jsonb_to_record(content) as ord(id int),
    LATERAL jsonb_to_record(content->'external_order_id') as ext(id text),
    LATERAL jsonb_to_record(content#>'{customer, external_customer_id}') as cus(id text)
    CROSS JOIN LATERAL jsonb_to_recordset(content->'line_items') line_items(sku text, properties jsonb, external_product_id jsonb, external_variant_id jsonb)
    cross join LATERAL jsonb_to_recordset(line_items.properties) props(name text, value text)
    

    【讨论】:

    • 完美,谢谢。我发现了一篇帖子,建议您可以将结果传递给下一个横向连接,但我不太清楚语法。看到答案就很明显了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-23
    • 2016-05-25
    • 2020-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多