PostgreSQL JSONB - 具有可变键名的查询条件
PostgreSQL JSONB - query condition with variable key names
我已经完成了各种 JSONB 教程:
- https://blog.codeship.com/unleash-the-power-of-storing-json-in-postgres/
- https://www.wagonhq.com/sql-tutorial/values-from-nested-json
- http://schinckel.net/2014/05/25/querying-json-in-postgres/
- http://stormatics.com/howto-use-json-functionality-in-postgresql/
考虑以下示例。
有一个table叫plans
。它有以下列:
id
(整数,自增主键)。
name
(字符串)。
structure
(jsonb).
结构列有一个具有以下结构的常规 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
键。
所以,我选择了第一种方式。
table有3条记录。对于这个问题,id
和 name
列的值并不重要。
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
之一。
感谢您阅读到这里!任何帮助将不胜感激。
I want to get all records which contain any objects with the is_invisible_node property set to 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)
I want to get all objects which contain regular_paper as one of its tags.
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)
我已经完成了各种 JSONB 教程:
- https://blog.codeship.com/unleash-the-power-of-storing-json-in-postgres/
- https://www.wagonhq.com/sql-tutorial/values-from-nested-json
- http://schinckel.net/2014/05/25/querying-json-in-postgres/
- http://stormatics.com/howto-use-json-functionality-in-postgresql/
考虑以下示例。
有一个table叫plans
。它有以下列:
id
(整数,自增主键)。name
(字符串)。structure
(jsonb).
结构列有一个具有以下结构的常规 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
键。
所以,我选择了第一种方式。
table有3条记录。对于这个问题,id
和 name
列的值并不重要。
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
之一。
感谢您阅读到这里!任何帮助将不胜感激。
I want to get all records which contain any objects with the is_invisible_node property set to 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)
I want to get all objects which contain regular_paper as one of its tags.
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)