SlideShare a Scribd company logo
CONQUERING
JSONB IN
POSTGRESQL
Ines Panker
Why did PostgreSQL add a
JSON data type?
Postgre SQL and NoSQL
Postgre 9.4 (December 2014) JSONB: Binary format, slower input, faster processing
JSON: Exact copy, same orderPostgre 9.2
No explicit
schema
Key-Value pairs in JSON are equal to
Key-Value pairs in columns
CREATE TABLE "PaymentRequest" (
"ID" bigint PRIMARY KEY NOT NULL,
"Created" timestamp without time zone,
"LastEdited" timestamp without time zone,
"Identifier" character varying(50),
"FinalPrice" double precision,
...,
"DeliveryTypeJSON" jsonb,
"DeliveryAddressJSON" jsonb,
"InvoiceAddressJSON" jsonb,
"PromotionCodeJSON" jsonb,
"PaymentJSON" jsonb);
CREATE TABLE "PaymentRequestEntry" (
"ID" bigint PRIMARY KEY NOT NULL,
"CartCount" integer DEFAULT 0,
"PriceWithTax" double precision,
"FullPriceWithTax" double precision,
"PriceNoTax" double precision,
"FullPriceNoTax" double precision,
...,
"ShopProductJSON" jsonb,
"PaymentRequestID" integer DEFAULT 0,
"VoucherID" integer DEFAULT 0
);
class ShopProduct{
private function DataForInvoice() {
$data = array(
'SKU' => $this->SKU,
'Title' => $this->LocaleTitle(),
'Variant' => $this->Variant,
'PriceWithTax' => $this->PriceWithTax(),
'PriceNoTax' => $this->PriceNoTax(),
'DiscountPriceWithTax'=> $this->PriceWithTax(true),
'DiscountPriceNoTax' => $this->PriceNoTax(true),
'Promotion' => $this->Promotion()->DataForInvoice(),
'TaxRate' => $this->TaxRate($nice = false),
'TaxPriceOfOne' => $this->TaxOfOneProduct(),
'NoTax' => $this->NoTax(),
'AllowOneStepTransaction' => $this->AllowOneStepTransaction,
'IsVoucher' => $this->IsVoucher,
....
);
return $data;
}
}
INSERT INTO "PaymentRequestEntry" VALUES (
1,
21.60,
24.00,
17.70,
19.67,
...,
'{
"SKU":"LJCRD-24-ADL",
"Title": "Visit Ljubljana Card, 24 hours",
"Variant": "Adult",
"PriceWithTax": 24.00,
"PriceNoTax": 19.67,
...,
"Promotion": {
"Code": "SUMMER17",
"DiscountPercent": 10.00,
"DiscountAmount": null,
"ActiveFrom": "2017-05-15 00:00:00"
"ActiveTo": "2017-06-15 00:00:00"
}
"TaxRate": 0.22
}',
845623
);
ERROR: invalid input syntax for type json
"ShopProductJSON"
-----------------------------------------------
{
"SKU": "LJCRD-24-ADL",
"NoTax": false,
"Title": "Visit Ljubljana Card, 24 hours",
"TaxRate": 0.22,
"Variant": "Adult",
"IsVoucher": false,
"Promotion": {
"Code": "SUMMER17",
"ActiveTo": "2017-06-15 00:00:00",
"ActiveFrom": "2017-05-15 00:00:00",
"DiscountAmount": null,
"DiscountPercent": "10.00"
},
"PriceNoTax": 19.67,
"TaxRateNice": 0.22,
"PriceWithTax": 24.00,
"DiscountPriceNoTax": 17.70,
"DiscountPriceWithTax": 21.60,
"AllowOneStepTransaction": 1,
...
}
SELECT "ShopProductJSON" FROM "PaymentRequestEntry" WHERE "ID" = 1
How to query??
select
"ID",
"WholePriceWithTax",
"NumberOfItems",
"ShopProductJSON"->>'SKU' AS "SKU",
"ShopProductJSON"->>'Title' as "Title",
"ShopProductJSON"->>'PriceWithTax' as "PriceWithTax",
"ShopProductJSON" from "PaymentRequestEntry"
WHERE "PaymentRequestID" = 1
ID
WholePrice
WithTax
NumberOf
Items SKU Title
PriceWith
Tax
1 21.6 1 LJCRD-24-ADL
Visit Ljubljana Card, 2
4 hours
24
2 90 2 TOUR-BIKE-24 Bike tour of Ljubljana 45
3 387 2 WC-17 WebCamp 2017 15
How to query??
(details)
JSON Operators: ->
arrays objects
int text
SELECT '["a",2,"3"]'::json->0 as data
data (json)
------------------
"a"
SELECT '["a",2,"3"]'::json->1 as data
data (json)
------------------
2
SELECT '["a",2,"3"]'::json->2 as data
data (json)
------------------
"3"
SELECT '["a",2,"3"]'::json->'a' as data
data (json)
------------------
SELECT '{"a":1,"b":2}'::json->'b' as data
data (json)
------------------
2
SELECT '{"a":1,"b":{"c":[1,2]}}'::json->'b'
data (json)
------------------
{"c":[1,2]}
json json
JSON Operators: ->>
arrays
int
SELECT '["a",2,"3"]'::json->>0 as data
data (text)
------------------
"a"
SELECT '["a",2,"3"]'::json->>1 > 1
ERROR: operator does not exist: text >
integer
SELECT ('["a",2,"3"]'::json->>1)::int > 1
data (boolean)
---------------
t
SELECT ('["a",2,"3"]'::json->1)::int > 1
ERROR: cannot cast type json to integer
text
JSON Operators: ->>
SELECT '{"a":1,"b":"word"}'::json->>'b'
data (text)
------------------
"word"
SELECT '{"a":1,"b":"word"}'::json->>'b' = 'word'
data(boolean)
-----------
t
SELECT
'{
"identifier":1mo3j4,
"items":[
{
"mon":"Monday",
"tue":"Tuesday"
},
{
"jan":"january",
"feb":"february"
}
]
}'::json->'items'->0->>'tue'
data (text)
--------------
"Tuesday"
objects
text text
JSON Operators: #>, #>>
SELECT
'{
"id":1,
"items":[
{
"mon":"Monday",
"tue":"Tuesday"
},
{
"jan":"january",
"feb":"february"
}
]
}'::json #>> '{items,0,tue}'
data (text)
--------------
"Tuesday"
SELECT
'{
"id":1,
"items":[
{
"mon":"Monday",
"tue":"Tuesday"
},
{
"jan":"january",
"feb":"february"
}
]
}'::json ->'items'->0->>'tue'
data (text)
--------------
"Tuesday"
objects
array of text text
JSONB Operators: @>, ?
SELECT
'{
"promotion":
{
"code":"SUMMER17",
"discount":"10"
}
}'::jsonb ? 'promotion'
SELECT
'{
"promotion":
{
"code":"SUMMER17",
"discount":"10"
}
}'::jsonb->'promotion' ? 'code'
SELECT
'{
"id":1,
"promotion":
{
"code":"SUMMER17",
"discount":"10"
}
}'::jsonb @> '{"promotion":{"code":
"SUMMER17"}}'
data (boolean)
--------------
t
objects
text boolean
objects
jsonb boolean
SELECT count("ID") as number_of_products_promo_was_used
FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}'
{
"SKU": "LJCRD-24-ADL",
"IsVoucher": false,
"Promotion": {
"Code": "SUMMER17",
},
"PriceNoTax": "19.67",
"TaxRateNice": "0.22",
"PriceWithTax": "24.00",
"DiscountPriceNoTax": "10.00",
"DiscountPriceWithTax": "10.00",
}
SELECT
"PaymentRequestID",
sum(("ShopProductJSON"->>'PriceWithTax')::float)
- sum(("ShopProductJSON"->>'DiscountPriceWithTax')::float) as money_saved
FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}‘
GROUP BY "PaymentRequestID"
PaymentRequestID money_saved
845623 5.12
845622 6.01
845625 2.2
...
SELECT
SUM("CartCount") AS number_of_products,
SUM(("ShopProductJSON"->>'PriceWithTax')::float) -
SUM(("ShopProductJSON"->>'DiscountPriceWithTax')::float) AS
money_saved,
r."DeliveryAddressJSON"->>'Country' AS country
FROM "PaymentRequestEntry" e
INNER JOIN "PaymentRequest" r ON r."ID" = e."PaymentRequestID"
WHERE "ShopProductJSON"->'Promotion'->>'Code' = 'SUMMER17'
GROUP BY r."DeliveryAddressJSON"->>'Country'
ORDER BY money_saved
number_of_products money_saved country
481 1503.72 DE
512 1438.56 AT
503 1289.05 IT
...
SELECT
sp."CalculatedPrice",
e."ShopProductJSON"->>'PriceWithTax' as bought_price,
e."Created"
FROM "PaymentRequestEntry" e
INNER JOIN "ShopProduct" sp
ON sp."SKU" = e."ShopProductJSON"->>'SKU'
AND e."ShopProductJSON" @> '{"SKU": "LJCRD-24-ADL"}'
ORDER BY e."Created" desc
CalculatedPrice bought_price Created
24 24 2017-04-21 15:23:01
24 21.6 2017-04-21 15:22:12
...
24 22 2016-12-01 07:17:53
...
EXPLAIN SELECT *
FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}'
Seq Scan on "PaymentRequestEntry" (cost=0.00..21.02 rows=3 width=100)
Filter: ((("ShopProductJSON" -> 'Promotion'::text) ->> 'Code'::text) =
'SUMMER17'::text)
GIN index
over the
WHOLE JSON
for only 1 key
in the JSON
jsonb_ops :
bigger & more
versatily
jsonb_path_ops:
smaller & supports
only @> querys
EXPLAIN SELECT * FROM "PaymentRequestEntry"
WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}'
Seq Scan on "PaymentRequestEntry" (cost=0.00..511091.51 rows=3662
width=85)
table "PaymentRequestEntry" size: 3635 MB, 2.807.147 rows
CREATE index json_index ON "PaymentRequestEntry"
USING GIN (("ShopProductJSON"->'Promotion'->'Code'))
CREATE index json_index ON "PaymentRequestEntry"
USING GIN ("ShopProductJSON")
@> <@
? ?| ?&
CREATE index json_index ON "PaymentRequestEntry"
USING GIN ("ShopProductJSON" jsonb_path_ops)
@>
indexname num_rows index_size
json_index_ops 2.807.147 10 MB
json_index_path_ops 2.807.147 7.832 MB (-20%)
json_index_column 2.807.147 3.112 MB (-70%)
json_index_column_path 2.807.147 3.112 MB (-70%)
1.
2.
3.
What have we used JSON
data types for so far?
Shop++
Changelog
JSON to Form
{
"type":"object",
"title":"Comment",
"properties":{
"name":{
"title":"Name",
"type":"string"
},
"email":{
"title":"Email",
"type":"string",
"pattern":"^S+@S+$",
"description":"Email will be used for evil."
},
"comment":{
"title":"Comment",
"type":"string",
"maxLength":20,
"validationMessage":"Don't be greedy!"
}
},
"required":[
"name",
"email",
"comment"
]
}
Evet Recurence Rules
REST API calls
The End

More Related Content

PDF
Embedding a language into string interpolator
PDF
Mobile Web 5.0
PDF
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
PDF
Mongo db for c# developers
PDF
Spray Json and MongoDB Queries: Insights and Simple Tricks.
PDF
The Ring programming language version 1.8 book - Part 49 of 202
DOC
quick json parser
PDF
MongoDB Performance Tuning
Embedding a language into string interpolator
Mobile Web 5.0
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
Mongo db for c# developers
Spray Json and MongoDB Queries: Insights and Simple Tricks.
The Ring programming language version 1.8 book - Part 49 of 202
quick json parser
MongoDB Performance Tuning

What's hot (20)

PDF
From mysql to MongoDB(MongoDB2011北京交流会)
PPTX
The rise of json in rdbms land jab17
ODP
2011 Mongo FR - Indexing in MongoDB
PPTX
How to leverage what's new in MongoDB 3.6
PDF
Mongoskin - Guilin
PDF
MongoDB Europe 2016 - Debugging MongoDB Performance
PDF
Inside MongoDB: the Internals of an Open-Source Database
KEY
CouchDB on Android
PDF
The Testing Games: Mocking, yay!
PDF
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
PPTX
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
PPTX
Data Governance with JSON Schema
PDF
Map/Confused? A practical approach to Map/Reduce with MongoDB
PPTX
ETL for Pros: Getting Data Into MongoDB
PDF
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
PPTX
Mongo db mug_2012-02-07
PDF
NoSQL を Ruby で実践するための n 個の方法
PDF
Nodejs mongoose
PPTX
MongoDB Aggregation
PDF
Native json in the Cache' ObjectScript 2016.*
From mysql to MongoDB(MongoDB2011北京交流会)
The rise of json in rdbms land jab17
2011 Mongo FR - Indexing in MongoDB
How to leverage what's new in MongoDB 3.6
Mongoskin - Guilin
MongoDB Europe 2016 - Debugging MongoDB Performance
Inside MongoDB: the Internals of an Open-Source Database
CouchDB on Android
The Testing Games: Mocking, yay!
MongoDB Europe 2016 - ETL for Pros – Getting Data Into MongoDB The Right Way
"Powerful Analysis with the Aggregation Pipeline (Tutorial)"
Data Governance with JSON Schema
Map/Confused? A practical approach to Map/Reduce with MongoDB
ETL for Pros: Getting Data Into MongoDB
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
Mongo db mug_2012-02-07
NoSQL を Ruby で実践するための n 個の方法
Nodejs mongoose
MongoDB Aggregation
Native json in the Cache' ObjectScript 2016.*
Ad

Similar to Conquering JSONB in PostgreSQL (20)

PDF
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
PDF
Oh, that ubiquitous JSON !
PDF
Postgre(No)SQL - A JSON journey
PPTX
PostgreSQL 9.4 JSON Types and Operators
PDF
No sql way_in_pg
PPT
The NoSQL Way in Postgres
 
PPTX
Power JSON with PostgreSQL
 
PPTX
Oracle Database - JSON and the In-Memory Database
PDF
Json in Postgres - the Roadmap
 
PPTX
Starting with JSON Path Expressions in Oracle 12.1.0.2
PDF
There is Javascript in my SQL
PDF
Postgrtesql as a NoSQL Document Store - The JSON/JSONB data type
PDF
PostgreSQL 9.3 and JSON - talk at PgOpen 2013
PDF
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
PDF
JSON Processing in the Database using PostgreSQL 9.4 :: Data Wranglers DC :: ...
PDF
Postgres vs Mongo / Олег Бартунов (Postgres Professional)
PDF
PDF
Working with JSON Data in PostgreSQL vs. MongoDB
PPTX
141115 dev opsdays_jso_ntosql
PDF
NoSQL для PostgreSQL: Jsquery — язык запросов
Webscale PostgreSQL - JSONB and Horizontal Scaling Strategies
Oh, that ubiquitous JSON !
Postgre(No)SQL - A JSON journey
PostgreSQL 9.4 JSON Types and Operators
No sql way_in_pg
The NoSQL Way in Postgres
 
Power JSON with PostgreSQL
 
Oracle Database - JSON and the In-Memory Database
Json in Postgres - the Roadmap
 
Starting with JSON Path Expressions in Oracle 12.1.0.2
There is Javascript in my SQL
Postgrtesql as a NoSQL Document Store - The JSON/JSONB data type
PostgreSQL 9.3 and JSON - talk at PgOpen 2013
Andrew Dunstan 9.3 JSON Presentation @ Postgres Open 2013
JSON Processing in the Database using PostgreSQL 9.4 :: Data Wranglers DC :: ...
Postgres vs Mongo / Олег Бартунов (Postgres Professional)
Working with JSON Data in PostgreSQL vs. MongoDB
141115 dev opsdays_jso_ntosql
NoSQL для PostgreSQL: Jsquery — язык запросов
Ad

Recently uploaded (20)

PPT
introduction to datamining and warehousing
PPT
Introduction, IoT Design Methodology, Case Study on IoT System for Weather Mo...
PPTX
CH1 Production IntroductoryConcepts.pptx
PDF
Digital Logic Computer Design lecture notes
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PDF
Unit I ESSENTIAL OF DIGITAL MARKETING.pdf
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PDF
Enhancing Cyber Defense Against Zero-Day Attacks using Ensemble Neural Networks
PDF
Operating System & Kernel Study Guide-1 - converted.pdf
PPTX
Current and future trends in Computer Vision.pptx
PPTX
web development for engineering and engineering
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PDF
PPT on Performance Review to get promotions
PDF
composite construction of structures.pdf
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PDF
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
PPTX
UNIT 4 Total Quality Management .pptx
PPTX
Internet of Things (IOT) - A guide to understanding
introduction to datamining and warehousing
Introduction, IoT Design Methodology, Case Study on IoT System for Weather Mo...
CH1 Production IntroductoryConcepts.pptx
Digital Logic Computer Design lecture notes
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Unit I ESSENTIAL OF DIGITAL MARKETING.pdf
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
Enhancing Cyber Defense Against Zero-Day Attacks using Ensemble Neural Networks
Operating System & Kernel Study Guide-1 - converted.pdf
Current and future trends in Computer Vision.pptx
web development for engineering and engineering
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PPT on Performance Review to get promotions
composite construction of structures.pdf
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
UNIT 4 Total Quality Management .pptx
Internet of Things (IOT) - A guide to understanding

Conquering JSONB in PostgreSQL

  • 2. Why did PostgreSQL add a JSON data type?
  • 3. Postgre SQL and NoSQL Postgre 9.4 (December 2014) JSONB: Binary format, slower input, faster processing JSON: Exact copy, same orderPostgre 9.2 No explicit schema Key-Value pairs in JSON are equal to Key-Value pairs in columns
  • 4. CREATE TABLE "PaymentRequest" ( "ID" bigint PRIMARY KEY NOT NULL, "Created" timestamp without time zone, "LastEdited" timestamp without time zone, "Identifier" character varying(50), "FinalPrice" double precision, ..., "DeliveryTypeJSON" jsonb, "DeliveryAddressJSON" jsonb, "InvoiceAddressJSON" jsonb, "PromotionCodeJSON" jsonb, "PaymentJSON" jsonb); CREATE TABLE "PaymentRequestEntry" ( "ID" bigint PRIMARY KEY NOT NULL, "CartCount" integer DEFAULT 0, "PriceWithTax" double precision, "FullPriceWithTax" double precision, "PriceNoTax" double precision, "FullPriceNoTax" double precision, ..., "ShopProductJSON" jsonb, "PaymentRequestID" integer DEFAULT 0, "VoucherID" integer DEFAULT 0 );
  • 5. class ShopProduct{ private function DataForInvoice() { $data = array( 'SKU' => $this->SKU, 'Title' => $this->LocaleTitle(), 'Variant' => $this->Variant, 'PriceWithTax' => $this->PriceWithTax(), 'PriceNoTax' => $this->PriceNoTax(), 'DiscountPriceWithTax'=> $this->PriceWithTax(true), 'DiscountPriceNoTax' => $this->PriceNoTax(true), 'Promotion' => $this->Promotion()->DataForInvoice(), 'TaxRate' => $this->TaxRate($nice = false), 'TaxPriceOfOne' => $this->TaxOfOneProduct(), 'NoTax' => $this->NoTax(), 'AllowOneStepTransaction' => $this->AllowOneStepTransaction, 'IsVoucher' => $this->IsVoucher, .... ); return $data; } }
  • 6. INSERT INTO "PaymentRequestEntry" VALUES ( 1, 21.60, 24.00, 17.70, 19.67, ..., '{ "SKU":"LJCRD-24-ADL", "Title": "Visit Ljubljana Card, 24 hours", "Variant": "Adult", "PriceWithTax": 24.00, "PriceNoTax": 19.67, ..., "Promotion": { "Code": "SUMMER17", "DiscountPercent": 10.00, "DiscountAmount": null, "ActiveFrom": "2017-05-15 00:00:00" "ActiveTo": "2017-06-15 00:00:00" } "TaxRate": 0.22 }', 845623 ); ERROR: invalid input syntax for type json
  • 7. "ShopProductJSON" ----------------------------------------------- { "SKU": "LJCRD-24-ADL", "NoTax": false, "Title": "Visit Ljubljana Card, 24 hours", "TaxRate": 0.22, "Variant": "Adult", "IsVoucher": false, "Promotion": { "Code": "SUMMER17", "ActiveTo": "2017-06-15 00:00:00", "ActiveFrom": "2017-05-15 00:00:00", "DiscountAmount": null, "DiscountPercent": "10.00" }, "PriceNoTax": 19.67, "TaxRateNice": 0.22, "PriceWithTax": 24.00, "DiscountPriceNoTax": 17.70, "DiscountPriceWithTax": 21.60, "AllowOneStepTransaction": 1, ... } SELECT "ShopProductJSON" FROM "PaymentRequestEntry" WHERE "ID" = 1
  • 9. select "ID", "WholePriceWithTax", "NumberOfItems", "ShopProductJSON"->>'SKU' AS "SKU", "ShopProductJSON"->>'Title' as "Title", "ShopProductJSON"->>'PriceWithTax' as "PriceWithTax", "ShopProductJSON" from "PaymentRequestEntry" WHERE "PaymentRequestID" = 1 ID WholePrice WithTax NumberOf Items SKU Title PriceWith Tax 1 21.6 1 LJCRD-24-ADL Visit Ljubljana Card, 2 4 hours 24 2 90 2 TOUR-BIKE-24 Bike tour of Ljubljana 45 3 387 2 WC-17 WebCamp 2017 15
  • 11. JSON Operators: -> arrays objects int text SELECT '["a",2,"3"]'::json->0 as data data (json) ------------------ "a" SELECT '["a",2,"3"]'::json->1 as data data (json) ------------------ 2 SELECT '["a",2,"3"]'::json->2 as data data (json) ------------------ "3" SELECT '["a",2,"3"]'::json->'a' as data data (json) ------------------ SELECT '{"a":1,"b":2}'::json->'b' as data data (json) ------------------ 2 SELECT '{"a":1,"b":{"c":[1,2]}}'::json->'b' data (json) ------------------ {"c":[1,2]} json json
  • 12. JSON Operators: ->> arrays int SELECT '["a",2,"3"]'::json->>0 as data data (text) ------------------ "a" SELECT '["a",2,"3"]'::json->>1 > 1 ERROR: operator does not exist: text > integer SELECT ('["a",2,"3"]'::json->>1)::int > 1 data (boolean) --------------- t SELECT ('["a",2,"3"]'::json->1)::int > 1 ERROR: cannot cast type json to integer text
  • 13. JSON Operators: ->> SELECT '{"a":1,"b":"word"}'::json->>'b' data (text) ------------------ "word" SELECT '{"a":1,"b":"word"}'::json->>'b' = 'word' data(boolean) ----------- t SELECT '{ "identifier":1mo3j4, "items":[ { "mon":"Monday", "tue":"Tuesday" }, { "jan":"january", "feb":"february" } ] }'::json->'items'->0->>'tue' data (text) -------------- "Tuesday" objects text text
  • 14. JSON Operators: #>, #>> SELECT '{ "id":1, "items":[ { "mon":"Monday", "tue":"Tuesday" }, { "jan":"january", "feb":"february" } ] }'::json #>> '{items,0,tue}' data (text) -------------- "Tuesday" SELECT '{ "id":1, "items":[ { "mon":"Monday", "tue":"Tuesday" }, { "jan":"january", "feb":"february" } ] }'::json ->'items'->0->>'tue' data (text) -------------- "Tuesday" objects array of text text
  • 15. JSONB Operators: @>, ? SELECT '{ "promotion": { "code":"SUMMER17", "discount":"10" } }'::jsonb ? 'promotion' SELECT '{ "promotion": { "code":"SUMMER17", "discount":"10" } }'::jsonb->'promotion' ? 'code' SELECT '{ "id":1, "promotion": { "code":"SUMMER17", "discount":"10" } }'::jsonb @> '{"promotion":{"code": "SUMMER17"}}' data (boolean) -------------- t objects text boolean objects jsonb boolean
  • 16. SELECT count("ID") as number_of_products_promo_was_used FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}' { "SKU": "LJCRD-24-ADL", "IsVoucher": false, "Promotion": { "Code": "SUMMER17", }, "PriceNoTax": "19.67", "TaxRateNice": "0.22", "PriceWithTax": "24.00", "DiscountPriceNoTax": "10.00", "DiscountPriceWithTax": "10.00", } SELECT "PaymentRequestID", sum(("ShopProductJSON"->>'PriceWithTax')::float) - sum(("ShopProductJSON"->>'DiscountPriceWithTax')::float) as money_saved FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}‘ GROUP BY "PaymentRequestID" PaymentRequestID money_saved 845623 5.12 845622 6.01 845625 2.2 ...
  • 17. SELECT SUM("CartCount") AS number_of_products, SUM(("ShopProductJSON"->>'PriceWithTax')::float) - SUM(("ShopProductJSON"->>'DiscountPriceWithTax')::float) AS money_saved, r."DeliveryAddressJSON"->>'Country' AS country FROM "PaymentRequestEntry" e INNER JOIN "PaymentRequest" r ON r."ID" = e."PaymentRequestID" WHERE "ShopProductJSON"->'Promotion'->>'Code' = 'SUMMER17' GROUP BY r."DeliveryAddressJSON"->>'Country' ORDER BY money_saved number_of_products money_saved country 481 1503.72 DE 512 1438.56 AT 503 1289.05 IT ...
  • 18. SELECT sp."CalculatedPrice", e."ShopProductJSON"->>'PriceWithTax' as bought_price, e."Created" FROM "PaymentRequestEntry" e INNER JOIN "ShopProduct" sp ON sp."SKU" = e."ShopProductJSON"->>'SKU' AND e."ShopProductJSON" @> '{"SKU": "LJCRD-24-ADL"}' ORDER BY e."Created" desc CalculatedPrice bought_price Created 24 24 2017-04-21 15:23:01 24 21.6 2017-04-21 15:22:12 ... 24 22 2016-12-01 07:17:53 ...
  • 19. EXPLAIN SELECT * FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}' Seq Scan on "PaymentRequestEntry" (cost=0.00..21.02 rows=3 width=100) Filter: ((("ShopProductJSON" -> 'Promotion'::text) ->> 'Code'::text) = 'SUMMER17'::text) GIN index over the WHOLE JSON for only 1 key in the JSON jsonb_ops : bigger & more versatily jsonb_path_ops: smaller & supports only @> querys
  • 20. EXPLAIN SELECT * FROM "PaymentRequestEntry" WHERE "ShopProductJSON" @> '{"Promotion":{"Code": "SUMMER17"}}' Seq Scan on "PaymentRequestEntry" (cost=0.00..511091.51 rows=3662 width=85) table "PaymentRequestEntry" size: 3635 MB, 2.807.147 rows CREATE index json_index ON "PaymentRequestEntry" USING GIN (("ShopProductJSON"->'Promotion'->'Code')) CREATE index json_index ON "PaymentRequestEntry" USING GIN ("ShopProductJSON") @> <@ ? ?| ?& CREATE index json_index ON "PaymentRequestEntry" USING GIN ("ShopProductJSON" jsonb_path_ops) @> indexname num_rows index_size json_index_ops 2.807.147 10 MB json_index_path_ops 2.807.147 7.832 MB (-20%) json_index_column 2.807.147 3.112 MB (-70%) json_index_column_path 2.807.147 3.112 MB (-70%) 1. 2. 3.
  • 21. What have we used JSON data types for so far?
  • 24. JSON to Form { "type":"object", "title":"Comment", "properties":{ "name":{ "title":"Name", "type":"string" }, "email":{ "title":"Email", "type":"string", "pattern":"^S+@S+$", "description":"Email will be used for evil." }, "comment":{ "title":"Comment", "type":"string", "maxLength":20, "validationMessage":"Don't be greedy!" } }, "required":[ "name", "email", "comment" ] }