在Postgres中遍历JSONB数组时的通配符

时间:2017-11-17 16:20:19

标签: arrays json postgresql jsonb

我们目前正在尝试将JSONB作为我们正在构建的系统中的订单数据的数据类型。由于文档相当大,以下是它的第一部分(重要部分):

{
"appMessage": {
    "order": {
        "customerSurname": "Tyreus",
        "shipment": {
            "asnNumber": "CC56477332",
            "shippingStore": "3321"
        },
        "orderNumber": "7991218655",
        "propositionCollectionStoreNumber": "5656",
        "collectionPointId": "4",
        "customerFirstname": "Isaac",
        "orderLine": [{
            "collectionWindowFrom": "2017-01-18T09:00:00+00:00",
            "lineNo": "1",
            "skuNo": "7654321",
            "createdDateTime": "2017-01-17T17:54:31+00:00",

我们面临的问题是将通配符应用于数组中的某些内容。使用上面的示例,我将如何进行通配符搜索以使用以7&#39开头的skuNo来检索所有记录?

在数组之外,我测试过通配符,例如:

SELECT 
    * 
FROM 
    ORDERS 
WHERE 
    ORDER_DATA->'appMessage'->'message'->>'enterpriseCode' LIKE 'TU%';

成功。但是一旦数组进入等式,一切都变得不清楚......

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用jsonb_array_elements取消JSONB数组,然后对其进行过滤:

--Using 'intermediary' table unnested_json_array
WITH test_data(json_column) AS (

    SELECT 
        jsonb_build_array(
            jsonb_build_object('lineNo', '1', 'skuNo', '7654321'), 
            jsonb_build_object('lineNo', '2', 'skuNo', '1654321'),
            jsonb_build_object('lineNo', '3', 'skuNo', '7654321')           
        )

), unnested_json_array(json_column) AS (    
    SELECT jsonb_array_elements((SELECT * FROM test_data))
) 
SELECT * FROM unnested_json_array WHERE json_column->>'skuNo' ILIKE '7%';

--Or even simpler using LATERAL JOIN   
WITH test_data(json_column) AS (
    SELECT 
        jsonb_build_array(
            jsonb_build_object('lineNo', '1', 'skuNo', '7654321'), 
            jsonb_build_object('lineNo', '2', 'skuNo', '1654321'),
            jsonb_build_object('lineNo', '3', 'skuNo', '7654321')           
        )
) 
SELECT 
    json_elements.* 
FROM 
    test_data 
    JOIN LATERAL jsonb_array_elements(test_data.json_column) AS json_elements (order_line) ON TRUE 
WHERE 
    order_line->>'skuNo' ILIKE '7%';

--In your case:
SELECT 
    json_elements.* 
FROM 
    ORDERS 
    JOIN LATERAL jsonb_array_elements(ORDER_DATA->'appMessage'->'order'->'orderLine') AS json_elements (order_line) ON TRUE 
WHERE 
    order_line->>'skuNo' LIKE '7%';