skip to Main Content

I need to update jsonb column by jsonb_set, to use jsonb_set, need a full Json Path. How could I get full jsonb path when jsonb has list?

For example, I got a JSON :

{
  "Laptop": {
    "brand": "Dell",
    "price": 1200,
    "specs": [
      {
        "name": "CPU",
        "Brand": "Intel"
      },
      {
        "name": "GPU",
        "Brand": "Nvdia"
      },
      {
        "name": "RAM",
        "Brand": "Kingston"
      }
    ]
  }
}

I need some query like

SELECT <full_path> 
  FROM table 
 WHERE jsonb_path_query_first(col,"$.Laptop.specs[*].name")::text='"CPU"'`;

I need a full path that matches the query above
the return could be

$.Laptop.specs[0].name or even better {Laptop,specs,0,name}

Is there any way to achieve this in Postgres?

2

Answers


  1. Chosen as BEST ANSWER

    In my case, for anyone facing the same problem, my current solution would be

    With
        json_data as (
            SELECT '{"Laptop": {"brand": "Dell", "price": 1200, "specs": [{"name": "CPU", "Brand": "Intel"}, {"name": "GPU", "Brand": "Nvdia"}, {"name": "RAM", "Brand": "Kingston"}]}}'::jsonb AS col
        ),
        found_match as (select ARRAY ['Laptop','specs',(ref.ord1 - 1)::text,'Brand'] as path
                         from json_data
                                  join LATERAL jsonb_array_elements(json_data-> 'Laptop' -> 'specs' ) with ordinality as ref(v, ord1)
                                       on true and ref.v ->> 'name' = 'CPU')
    update <table> set json_data=jsonb_set(<table>.<col>,fm.path, cast ('AMD' as jsonb))
    from found_match fm where <table>.id=fm.id;
    

  2. Based on my understanding you need the index of the path? let me know

    WITH json_data AS (
        SELECT '{"Laptop": {"brand": "Dell", "price": 1200, "specs": [{"name": "CPU", "Brand": "Intel"}, {"name": "GPU", "Brand": "Nvdia"}, {"name": "RAM", "Brand": "Kingston"}]}}'::jsonb AS col
    )
    SELECT 
        CONCAT('$.Laptop.specs[', idx - 1, '].name') AS full_json_path
    FROM 
        json_data,
        LATERAL jsonb_array_elements(col->'Laptop'->'specs') WITH ORDINALITY arr(elem, idx)
    WHERE 
        elem->>'name' = 'CPU';
    

    Output

    $.Laptop.specs[0].name
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search