PostgreSQL JSONB - 具有变量键名

时间:2016-07-13 08:56:58

标签: json postgresql jsonb

我已经阅读了各种JSONB教程:

请考虑以下示例。

有一个名为plans表格。它包含以下列:

  1. id(整数,自动递增主键)。
  2. name(字符串)。
  3. structure(jsonb)。
  4. 结构列具有常规JSON对象,具有以下结构:

    {
      "some_unique_id": {
        "key1": "valueA",   // Fixed key name.
        "key2": "valueB"    // Fixed key name.
      },
      "another_unique_id": {
        "key1": "valueC",   // Fixed key name.
        "key2": "valueB"    // Fixed key name.
      },
      ...                   // can go on up to a 1000 items.
    }
    

    注意:最外面的键是动态的。它们会针对每个项目进行更改。 这些值只是常规的JSON对象。没什么特别的。

    我使用UUID作为结构中的键,因此如果我知道它的UUID,则很容易查找和检索特定值。

    另一个选项是使我的结构成为一个对象数组(并将UUID作为值放在每个对象中),如下所示:

    [
      {
        "uuid": "some_unique_id",
        "key1": "valueA",   // Fixed key name.
        "key2": "valueB"    // Fixed key name.
      },
      {
        "uuid": "another_unique_id",
        "key1": "valueC",   // Fixed key name.
        "key2": "valueB"    // Fixed key name.
      },
      ...                   // can go on up to a 1000 items.
    ]
    

    在后一种方法中,要使用其UUID检索特定对象,我必须遍历整个数组并匹配每个对象的uuid键。

    所以,我选择了第一种方法。

    该表有3条记录。对于此问题,idname列的值并不重要。

    3条记录中structure列的实际值如下所示。

    记录1:

    {
      "bab6246d-802c-4b80-af41-ab15fd1541b4": {
        "name": "Sanskrit",
        "children_uuids": [
          "fa42b4b2-a958-42f1-af33-314e8e1fb6a6",
          "3aeeadfe-6ad4-4229-85a5-5de030c08014"
        ],
        "is_invisible_node": true,
        "tags": [
          "paper",
          "course_paper"
        ],
        "type": "course_paper"
      },
      "dbc33473-8453-4cf9-8ecf-d8013283b0d8": {
        "name": "French",
        "children_uuids": [
          "4bf65ff9-3b11-42d5-a744-adcd1fd5a953"
        ],
        "is_invisible_node": true,
        "tags": [
          "paper",
          "course_paper"
        ],
        "type": "course_paper"
      }
    }
    

    记录2:

    {
      "ed6164d0-fdc0-4259-90a5-fd60d9d716dc": {
        "name": "Pen and Paper Assessment 1",
        "children_uuids": [
    
        ],
        "is_invisible_node": false,
        "tags": [
          "paper",
          "assessment"
        ],
        "type": "assessment"
      },
      "059d0116-bca2-49f1-b333-58c4dbec8566": {
        "name": "Content",
        "children_uuids": [
    
        ],
        "is_invisible_node": false,
        "tags": [
          "paper",
          "assessment"
        ],
        "type": "assessment"
      }
    }
    

    记录3:

    {
      "63619c7f-fa73-49af-9df5-4be1eb38cee5": {
        "name": "Q12",
        "children_uuids": [
    
        ],
        "is_invisible_node": true,
        "tags": [
          "paper",
          "regular_paper"
        ],
        "type": "regular_paper"
      },
      "56eed164-17f7-48e9-b3ce-b5b469e8cb0e": {
        "name": "Q13",
         "children_uuids": [
    
        ],
        "is_invisible_node": false,
        "tags": [
          "paper",
          "regular_paper"
        ],
        "type": "regular_paper"
      },
      "69d202c1-5c23-412f-860d-1a5d705c31b3": {
        "name": "Q14",
        "children_uuids": [
    
        ],
        "is_invisible_node": false,
        "tags": [
          "paper",
          "regular_paper"
        ],
        "type": "regular_paper"
      }
    }
    

    现在,我如何编写查询来执行以下两项操作?

    • 我想获取所有记录,其中包含is_invisible_node属性设置为true的所有对象。
    • 我希望将包含regular_paper的所有对象作为其tags之一。

    感谢您阅读此内容!任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:8)

  

我想获取所有包含is_invisible_node属性设置为true的对象的记录。

使用jsonb_each()检索第二级对象:

select id, uuid.key uuid
from 
    plans, 
    jsonb_each(structure) uuid
where (value->>'is_invisible_node')::boolean;

 id |                 uuid                 
----+--------------------------------------
  1 | bab6246d-802c-4b80-af41-ab15fd1541b4
  1 | dbc33473-8453-4cf9-8ecf-d8013283b0d8
  3 | 63619c7f-fa73-49af-9df5-4be1eb38cee5
(3 rows)

select distinct id
from 
    plans, 
    jsonb_each(structure) uuid
where (value->>'is_invisible_node')::boolean;

 id 
----
  1
  3
(2 rows)    
  

我希望将包含regular_paper的所有对象作为其标记之一。

json对象tags是一个数组,所以jsonb_array_elements_text()不需要它:

select uuid.key uuid
from 
    plans, 
    jsonb_each(structure) uuid,
    jsonb_array_elements_text(value->'tags') tag
where tag = 'regular_paper';

                 uuid                 
--------------------------------------
 56eed164-17f7-48e9-b3ce-b5b469e8cb0e
 63619c7f-fa73-49af-9df5-4be1eb38cee5
 69d202c1-5c23-412f-860d-1a5d705c31b3
(3 rows)