[英]How to query nested JSONB postgres in Rails
我有一個名為Order的表,其jsonb列類型名為line_items 。 line_items列可以包含這樣的嵌套值:
[
{
"id":9994857545813,
"sku":"CLIPPING-PATH_C2_24H",
},
{
"id":9994857578581,
"sku":"NATURAL-SHADOW_C1_24H",
}
]
上面的示例中有兩個訂單項,但它可以從 1 到任意數量的訂單項不等。
我需要查詢僅包含 1 個訂單項的所有訂單,其中 sku = 特定值,例如CLIPPING-PATH_C2_24H ,如上例所示。
因此,查詢不應與上述示例匹配,而是以下僅包含 1 個行項目且 sku=CLIPPING-PATH_C2_24H
[
{
"id":9994857545813,
"sku":"CLIPPING-PATH_C2_24H",
}
]
可以幫助使用 Rails 活動記錄編寫查詢嗎?
演示
您可以在 ruby 中調用 plpghsql。( 如何從 Ruby on rails 調用 plpgsql 函數? )
sql 查詢: select jsonb_path_query(order_json,'$[*] ? (@.sku == "CLIPPING-PATH_C2_24H")') from orders ;
正確處理並不容易,因為 PL/pgsql 函數字符串的某些部分甚至包含 4 個單引號。 最好使用 raise notice 來逐步測試。
CREATE OR REPLACE FUNCTION get_sku_CLIPPING_path (_sku text)
RETURNS json
AS $$
DECLARE
_sql text;
_returnjson jsonb;
BEGIN
RAISE NOTICE '%: _sku', $1;
RAISE NOTICE '%', '$[*] ? (@.sku == ' || $1 || ')';
RAISE NOTICE '%', $s$
SELECT
jsonb_path_query(order_json, $s$ || '''' || '$[*] ? (@.sku == ' || $1 || ')''' || ' from orders';
_sql := $s$
SELECT
jsonb_path_query(order_json, $s$ || '''' || '$[*] ? (@.sku == ' || $1 || ')''' || ' )from orders';
EXECUTE _sql
USING _sku INTO _returnjson;
RETURN (_returnjson::json);
END
$$
LANGUAGE plpgsql;
調用它: select * from get_sku_CLIPPING_path('"CLIPPING-PATH_C2_24H"');
首先,您沒有嵌套的 json。 你只有一個帶有對象的 json 數組。 此外,您的 json 對象可以表示為表格。 最好將這些對象存儲在另一個表中並設置一對多關系。 你可以有一個“orders”表和一個“order_details”表。
要獲取您需要的數據,首先我們需要找到具有"sku":"CLIPPING-PATH_C2_24H"
記錄,然后我們需要解析 json 並從 line_items 字段中獲取該對象。
SELECT
t.*
FROM orders o,
-- extract object from array of json objects
LATERAL jsonb_path_query(o.line_items, '$[*] ? (@.sku == $value)', '{"value" : "CLIPPING-PATH_C2_24H"}') order_line,
-- convert "sku":"NATURAL-SHADOW_C1_24H" into columns
LATERAL jsonb_to_record(order_line) as t(id bigint, sku text)
WHERE
-- find record which has "sku":"NATURAL-SHADOW_C1_24H"
o.line_items @> '[{"sku":"NATURAL-SHADOW_C1_24H"}]';
結果會是這樣;
id | sku ------------- | -------------------- 9994857545813 | CLIPPING-PATH_C2_24H
小提琴在這里
我能夠使用 jsonb_array_length 方法解決這個問題:
Order
.where("line_items @> ?", [{sku: sku}].to_json)
.where("jsonb_array_length(line_items) = 1")
.count
end
以下資源非常有幫助: https ://gist.github.com/mankind/1802dbb64fc24be33d434d593afd6221
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.