forked from dbu/postgres-json
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathqueries.sql
167 lines (137 loc) · 7.66 KB
/
queries.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
SELECT COUNT(*) FROM auction_json WHERE item->>'author' = 'Author 1';
SELECT COUNT(*) FROM auction_json_indexed WHERE item->>'author' = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb WHERE item->>'author' = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item->>'author' = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb_gin WHERE item->>'author' = 'Author 1';
SELECT COUNT(*) FROM auction_generated_fields WHERE author = 'Author 1';
SELECT COUNT(*) FROM auction_generated_fields_indexed WHERE author = 'Author 1';
-- extract the value from json, rather than compare with a json string
SELECT COUNT(*) FROM auction_jsonb WHERE item->>'author' = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb WHERE item->'author' = '"Author 1"';
-- alternatively, use json path functions
-- json path is very powerful, similar to xpath or css selectors
-- CREATE INDEX jsonb_author_path ON auction_jsonb_indexed ((json_value(item, '$.author')));
-- new in postgres 17
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE json_value(item, '$.author') = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb_gin WHERE json_value(item, '$.author') = 'Author 1';
-- with older postgres, you have jsonb_path_query but that returns a set, not a value
SELECT jsonb_path_query(item, '$.author') FROM auction_jsonb_indexed LIMIT 1;
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE jsonb_path_exists(item, '$.author');
-- alternatively access elements in object with a (potentially multi level) array of keys
-- does not share index with arrow notation, but can have its own index
-- CREATE INDEX jsonb_author_contain ON auction_jsonb_indexed ((item #>> '{author}'));
SELECT item #> '{"author"}' AS author FROM auction_jsonb_indexed LIMIT 1;
SELECT item #>> '{"author"}' AS author FROM auction_jsonb_indexed LIMIT 1;
SELECT COUNT(*) FROM auction_jsonb WHERE item #>> '{"author"}' = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item #>> '{"author"}' = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb_gin WHERE item #>> '{"author"}' = 'Author 1';
-- or you can access fields like you would in PHP
-- again does not share index with arrow or # notation, but can have its own index
-- CREATE INDEX jsonb_author_hashnotation ON auction_jsonb_indexed ((item['author']));
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item['author']->>0 = 'Author 1';
SELECT COUNT(*) FROM auction_jsonb_gin WHERE item['author']->>0 = 'Author 1';
-- semantically equivalent but massively slower
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item['author'] = '"Author 1"';
-- querying for containing value (only available with jsonb)
-- this does not use the index, but can use the GIN
SELECT COUNT(*) FROM auction_jsonb WHERE item @> '{"author": "Author 1"}';
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item @> '{"author": "Author 1"}';
SELECT COUNT(*) FROM auction_jsonb_gin WHERE item @> '{"author": "Author 1"}';
-- has field (? or jsonb_exists are the same construct)
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item ? 'author';
SELECT COUNT(*) FROM auction_jsonb WHERE jsonb_exists(item, 'author');
SELECT COUNT(*) FROM auction_jsonb_gin WHERE jsonb_exists(item, 'author');
-- has any of the fields
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item ?| array['author', 'foobar'];
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE jsonb_exists_any(item, array['author', 'foobar']);
SELECT COUNT(*) FROM auction_jsonb_gin WHERE item ?| array['author', 'foobar'];
-- has all the specified fields
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE item ?& array['author', 'title'];
SELECT COUNT(*) FROM auction_jsonb_indexed WHERE jsonb_exists_all(item, array['author', 'title']);
SELECT COUNT(*) FROM auction_jsonb_gin WHERE item ?& array['author', 'title'];
-- unwrap objects
SELECT item FROM auction_jsonb LIMIT 1;
SELECT json_serialize(item) FROM auction_json LIMIT 1;
SELECT jsonb_each_text(item) FROM auction_jsonb LIMIT 10;
SELECT jsonb_path_query(item, '$.genre') FROM auction_jsonb LIMIT 1;
-- updating
SELECT item->>'author' AS old FROM auction_jsonb WHERE id=41;
UPDATE auction_jsonb
SET item = jsonb_set(item, '{author}', '"New Author"', true)
WHERE id=41;
SELECT item->>'author' AS new FROM auction_jsonb WHERE id=41;
-- only update property if exists, but don't create
SELECT item->>'foo' AS old FROM auction_jsonb WHERE id=42;
UPDATE auction_jsonb
SET item = jsonb_set(item, '{foo}', '"Bar"', false)
WHERE id=42;
SELECT item->>'foo' AS new FROM auction_jsonb WHERE id=42;
-- create property if not exists
UPDATE auction_jsonb SET item = item - 'foo' WHERE id=43;
SELECT item->>'foo' AS old FROM auction_jsonb WHERE id=43;
UPDATE auction_jsonb
SET item = jsonb_set(item, '{foo}', '"Bar"', true)
WHERE id=43;
SELECT item->>'foo' AS new FROM auction_jsonb WHERE id=43;
UPDATE auction_jsonb SET item = jsonb_set(item, '{author}', '"Author 4"') WHERE id=44;
SELECT item->>'author' AS old FROM auction_jsonb WHERE id=44;
UPDATE auction_jsonb
SET item = jsonb_set(item, '{author}', 'null')
WHERE id=44;
SELECT item->'author' AS new FROM auction_jsonb WHERE id=44;
-- deleting
SELECT item->>'author' AS old FROM auction_jsonb WHERE id=50;
UPDATE auction_jsonb
SET item = item - 'author'
WHERE id=50;
SELECT item->>'author' AS new FROM auction_jsonb WHERE id=50;
SELECT item->>'author' AS old FROM auction_jsonb WHERE id=51;
UPDATE auction_jsonb
SET item = item - array['author', 'title']
WHERE id=51;
SELECT item->>'author' AS new FROM auction_jsonb WHERE id=51;
SELECT item->'author' AS old FROM auction_jsonb WHERE id=52;
UPDATE auction_jsonb
SET item = jsonb_set_lax(item, '{author}', null, true, 'delete_key')
WHERE id=52;
SELECT item->'author' AS new FROM auction_jsonb WHERE id=52;
-- fun with jsonb_set_lax
UPDATE auction_jsonb SET item = jsonb_set(item, '{author}', '"Author 3"', true) WHERE id=60;
SELECT item->'author' AS old FROM auction_jsonb WHERE id=60;
UPDATE auction_jsonb
SET item = jsonb_set_lax(item, '{author}', null)
WHERE id=60;
SELECT item->'author' AS new FROM auction_jsonb WHERE id=60;
SELECT item->'author' AS old FROM auction_jsonb WHERE id=61;
UPDATE auction_jsonb
SET item = jsonb_set_lax(item, '{author}', null, true, 'return_target')
WHERE id=61;
SELECT item->'author' AS new FROM auction_jsonb WHERE id=61;
SELECT jsonb('{"type":"book", "author": "Author 1"}') AS create_item;
SELECT '{"type":"book", "author": "Author 1"}'::jsonb AS cast_item;
SELECT * FROM jsonb_each((SELECT item FROM auction_jsonb WHERE id=1));
-- Some deep JSON, they only work when the fixtures have been loaded through Symfony with the --extra-data option
SELECT item #> '{key-0-1,key-1-1,key-2-2,key-3-2}' AS old FROM auction_jsonb WHERE id=60;
UPDATE auction_jsonb SET item = jsonb_set(item, '{key-0-1,key-1-1,key-2-2,key-3-2}', '"Deep"', true) WHERE id<1000;
SELECT item #> '{key-0-1,key-1-1,key-2-2,key-3-2}' AS new FROM auction_jsonb WHERE id=60;
SELECT item #> '{key-0-1,key-1-1,key-2-2,key-3-2}' AS old FROM auction_jsonb_gin LIMIT 1;
UPDATE auction_jsonb_gin SET item = jsonb_set(item, '{key-0-1,key-1-1,key-2-2,key-3-2}', '"Deop"', true) WHERE id>0;
SELECT item #> '{key-0-1,key-1-1,key-2-2,key-3-2}' AS new FROM auction_jsonb_gin WHERE id=60;
SELECT
table_name,
pg_size_pretty(table_size) AS table_size,
pg_size_pretty(indexes_size) AS indexes_size,
pg_size_pretty(total_size) AS total_size
FROM (
SELECT
table_name,
pg_table_size(table_name) AS table_size,
pg_indexes_size(table_name) AS indexes_size,
pg_total_relation_size(table_name) AS total_size
FROM (
SELECT ('"public"."' || table_name || '"') AS table_name
FROM information_schema.tables
WHERE table_schema = 'public'
) AS all_tables
ORDER BY total_size DESC
) AS pretty_sizes;