簡體   English   中英

從 jsonb 列中獲取特定值

[英]Get specific values from a jsonb column

我有一個表Customer

  • 客戶 ID(整數)
  • 客戶名稱(字符串)
  • 客戶訂單(jsonB)

customerOrders具有以下結構:

{ 
 "nodeValue":[
   { 
      "key": "key1",
      "value": "value1"
   },
   { 
      "key": "key2",
      "value": "value2"
   },
   { 
      "key": "key3",
      "value": "value3"
   },
   { 
      "key": "key4",
      "value": "value4"
   },
   { 
      "key": "key5",
      "value": "value5"
   }
 ]
}

我正在嘗試獲取行key = 'key3' AND key = 'key4'nodeValue的值。

例如:返回 'key3' 和 'key4' 的值, WHERE key = 'key3' AND key = 'key4'

我正在嘗試執行以下操作:

SELECT value, value 
from public.customers 
where nodeValue.key3 = 'key3' 
  AND nodeValue.key4 = 'key4'
with orders as 
(
   select jsonb_array_elements(customerOrders->'nodeValue') as orders
   from customers
) 
select orders->'value' as val 
from orders 
where 
    orders->>'key' = 'key3' 
or  orders->>'key' = 'key4';

結果:

值1

值2

請注意使用運算符 ->> 以文本形式獲取值

數據庫小提琴

獲取key = 'key3' AND key = 'key4'的行的nodeValue值。

最好使用jsonb “包含”運算符@>

SELECT customerid, customerOrders->'nodeValue'
FROM   customer
WHERE  customerOrders->'nodeValue' @> '[{"key": "key3"}]'
AND    customerOrders->'nodeValue' @> '[{"key": "key4"}]';

為了使大表快速支持它,請使用索引。 理想情況下是一個jsonb_path_ops索引:

CREATE INDEX customer_nodeValue_idx ON customer
USING gin ((customerOrders->'nodeValue') jsonb_path_ops);  -- parentheses required

看:

你的問題的最新版本有點棘手:

返回“KEY3”和“KEY4”的價值

SELECT c.customerid, o.values
FROM   customer c
CROSS  JOIN LATERAL (
   SELECT ARRAY(
      SELECT o.ord->>'value'
      FROM   jsonb_array_elements(c.customerOrders->'nodeValue') o(ord)
      WHERE (o.ord->>'key' = 'key3' OR
             o.ord->>'key' = 'key4')
      )
   ) o(values)
WHERE  c.customerOrders->'nodeValue' @> '[{"key": "key3"}]'
AND    c.customerOrders->'nodeValue' @> '[{"key": "key4"}]';

首先過濾符合上述條件的行(使用快速索引查找)。 然后取消嵌套 JSON 文檔並在LATERAL子查詢中構建您的答案。 應該是最簡單、最干凈和最快的。 有關技術,請參閱:

我將customerid添加到兩個查詢的結果中以標識行。 那是可選的。

db<> 在這里小提琴(展示兩者)

設計

您可以將臃腫的 JSON 布局簡化為:

'{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
    "key4": "value4",
    "key5": "value5"
}'

或者至少:

'[
    {
        "key1": "value1"
    },
    {
        "key2": "value2"
    },
    {
        "key3": "value3"
    },
    {
        "key4": "value4"
    },
    {
        "key5": "value5"
    }
]'

將使一切變得更簡單、更小、更快。

我懷疑你真正想要的是

SELECT
  (SELECT orders->>'value'
    FROM json_array_elements(customerOrders->'nodeValue') AS orders
    WHERE orders->>'key' = 'key3'
  ) AS value_key3,
  (SELECT orders->>'value'
    FROM json_array_elements(customerOrders->'nodeValue') AS orders
    WHERE orders->>'key' = 'key4'
  ) AS value_key4
FROM public.customers;

但實際上您的數據結構不適合此目的。 使用具有鍵和值作為屬性的對象,而不是具有鍵值對的數組。 這樣,您就可以輕松訪問結果

SELECT
  customerOrders->'nodeValue'->>'key3' AS value_key3,
  customerOrders->'nodeValue'->>'key4' AS value_key4
FROM public.customers;

首先你需要創建一個類型(或表)

CREATE TYPE key_value_type AS (
    key text,
    value text
);

然后你可以使用jsonb_populate_recordset函數

SELECT
    r_key1.value AS key1,
    r_key2.value AS key2
FROM
    customers c
    JOIN LATERAL jsonb_populate_recordset(NULL::key_value_type, customerOrders -> 'nodeValue') r_key1 
      ON r_key1.key = 'key1'
    JOIN LATERAL jsonb_populate_recordset(NULL::key_value_type, customerOrders -> 'nodeValue') r_key2 
      ON r_key2.key = 'key2'

或者使用jsonb_to_recordset函數(不創建類型)

SELECT
    r_key1.value AS key1,
    r_key2.value AS key2
FROM
    customers c
    JOIN LATERAL jsonb_to_recordset(customerOrders -> 'nodeValue') AS r_key1 (key text,
        value text) ON r_key1.key = 'key1'
    JOIN LATERAL jsonb_to_recordset(customerOrders -> 'nodeValue') AS r_key2 (key text,
        value text) ON r_key2.key = 'key2'

這是兩種選擇的結果;

| key1   | key2   |
| ------ | ------ |
| value1 | value2 |

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM