簡體   English   中英

如何在 Rails 中查詢嵌套的 JSONB postgres

[英]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.

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