PostgreSql中Jsonb对象解析

Jsonb object parsing in PostgreSql

如何在 PostgreSql 中解析 jsonb 对象。问题是 - 对象每次都因内部结构而异。就像下面一样。

{  
   "1":{  
      "1":{  
         "level":2,
         "nodeType":2,
         "id":2,
         "parentNode":1,
         "attribute_id":363698007,
         "attribute_text":"Finding site",
         "concept_id":386108004,
         "description_text":"Heart tissue",
         "hierarchy_id":0,
         "description_id":-1,
         "deeperCnt":0,
         "default":false
      },
      "level":1,
      "nodeType":1,
      "id":1,
      "parentNode":0,
      "concept_id":22253000,
      "description_id":37361011,
      "description_text":"Pain",
      "hierarchy_id":404684003,
      "deeperCnt":1,
      "default":false
   },
   "2":{  
      "1":{  
         "attribute_id":"363698007",
         "attribute_text":"Finding site (attribute)",
         "value_id":"321667001",
         "value_text":"Respiratory tract structure (body structure)",
         "default":true
      },
      "level":1,
      "nodeType":1,
      "id":3,
      "parentNode":0,
      "concept_id":11833005,
      "description_id":20419011,
      "description_text":"Dry cough",
      "hierarchy_id":404684003,
      "deeperCnt":1,
      "default":false
   },
   "level":0,
   "recAddedLevel":1,
   "recAddedId":3,
   "nodeType":0,
   "multiple":false,
   "currNodeId":3,
   "id":0,
   "lookForAttributes":false,
   "deeperCnt":2,

}

那么我应该如何解析所有对象,例如查看对象内部是否有 "attribute_id" = 363698007? 在这种情况下,我们应该在 PostgreSql 中使用 WHERE 语句 'true' 而 selecting 数据行。

2 个问题 - 我应该为 jsonb 列使用什么索引以获得想要的结果? 已经尝试创建 btree 和 gin 索引,但即使是简单的 select returns 'null' 和 sql 也像这样:

SELECT object::jsonb -> 'id' AS id
    FROM table;

如果我使用这个:

SELECT object
    FROM table;

returns首先描述对象。

快速而肮脏的方式(扩展到):

WITH RECURSIVE doc_key_and_value_recursive(id, key, value) AS (
  SELECT
    my_json.id,
    t.key,
    t.value
  FROM my_json, jsonb_each(my_json.data) AS t

  UNION ALL

  SELECT
    doc_key_and_value_recursive.id,
    t.key,
    t.value
  FROM doc_key_and_value_recursive,
    jsonb_each(CASE 
      WHEN jsonb_typeof(doc_key_and_value_recursive.value) <> 'object' THEN '{}'::jsonb
      ELSE doc_key_and_value_recursive.value
    END) AS t
)
SELECT t.id, t.data->'id' AS id
FROM doc_key_and_value_recursive AS c
INNER JOIN my_json AS t ON (t.id = c.id)
WHERE
    jsonb_typeof(c.value) <> 'object'
    AND c.key = 'attribute_id'
    AND c.value = '363698007'::jsonb;

在线示例:https://dbfiddle.uk/?rdbms=postgres_11&fiddle=57b7c4e817b2dd6580bbf28cbac10981

一旦找到相关键和值就停止递归,反向排序和限制 1,这可能会得到很大改善。但它一般会做基本的事情。

它还表明 jsonb->'id' 确实按预期工作。