Anyquery is not strictly normalized. It can handle JSON arrays and objects in columns. Those are stored as text and can be queried using JSON functions. Most plugins return JSON data, so it’s essential to know how to work with them.
Let’s say we have a product table with a column containing an array of tags:
id
name
tags
1
Apple
[“fruit”, “red”, “sweet”]
2
Carrot
[“vegetable”, “orange”, “healthy”]
To calculate the number of tags for each product, you can use the json_array_length function:
SELECT name , json_array_length(tags) AS number_of_tags
name
number_of_tags
Apple
3
Carrot
3
To explode the tags into separate rows, you can use the json_each virtual table:
SELECT name , value AS tag
FROM products, json_each(tags) ;
name
tag
Apple
fruit
Apple
red
Apple
sweet
Carrot
vegetable
Carrot
orange
Carrot
healthy
From that, you have a normalized view of the tags.
To filter products by a specific tag, you can use the json_has function (from 0.3.2):
WHERE json_has(tags, 'fruit' ) ;
-- Insert 'juicy' into the tags of all products at the end
SELECT name , json_insert(tags, '$[#]' , 'juicy' ) AS tags
name
tags
Apple
[“fruit”,“red”,“sweet”,“juicy”]
Carrot
[“vegetable”,“orange”,“healthy”,“juicy”]
-- Replace 'red' or 'orange' with 'green' in the tags of all products
SELECT name , json_replace(tags, '$[1]' , 'green' ) AS tags
name
tags
Apple
[“fruit”,“green”,“sweet”]
Carrot
[“vegetable”,“green”,“healthy”]
-- Remove the last tag from the tags of all products
SELECT name , json_remove(tags, '$[#-1]' ) AS tags
name
tags
Apple
[“fruit”,“red”]
Carrot
[“vegetable”,“orange”]
-- Create an array with 'fruit' and 'green' for all products
SELECT name , json_array ( 'fruit' , 'green' ) AS tags
name
tags
Apple
[“fruit”,“green”]
Carrot
[“fruit”,“green”]
Let’s say we have a product table with a column containing a JSON object:
id
name
properties
1
Apple
{“color”: “red”, “taste”: “sweet”, “tags”: [“fruit”, “red”, “sweet”]}
2
Carrot
{“color”: “orange”, “taste”: “sweet”, “tags”: [“vegetable”, “orange”, “healthy”]}
To extract a field from the JSON object, you can use the json_extract function or its shorthand ->>. You need to provide a JSON path. The object is referenced by $. To access a field, use $.<field>. And for an array, use $[<index>]. To get all elements of an array, use $[*].
SELECT name , properties- >> '$.color' AS color
SELECT name , json_extract(properties, '$.color' ) AS color
name
color
Apple
red
Carrot
orange
Similarly, you can extract an array from the JSON object:
SELECT name , value AS tag
FROM products2, json_each(properties- > '$.tags' ) ;
name
tag
Apple
fruit
Apple
red
Apple
sweet
Carrot
vegetable
Carrot
orange
Carrot
healthy
To ensure a field exists in the JSON object, you can use the json_has function:
SELECT name , json_has(properties, 'color' ) AS has_color_field
name
has_color_field
Apple
1
Carrot
1
-- Insert or replace a 'price' field with 1.5 for all products
SELECT name , json_set(properties, '$.price' , 1 . 5 ) AS properties
name
properties
Apple
{“color”:“red”,“taste”:“sweet”,“tags”:[“fruit”,“red”,“sweet”],“price”:1.5}
Carrot
{“color”:“orange”,“taste”:“sweet”,“tags”:[“vegetable”,“orange”,“healthy”],“price”:1.5}
-- Create a new object with 'color' and 'price' for all products
SELECT name , json_object ( 'color' , 'brown' , 'price' , 2 . 5 ) AS properties
name
properties
Apple
{“color”:“brown”,“price”:2.5}
Carrot
{“color”:“brown”,“price”:2.5}
-- Filter products by color
WHERE properties- >> '$.color' = 'red' ;
-- Remove the 'color' field from all products
SELECT name , json_remove(properties, '$.color' ) AS properties
name
properties
Apple
{“taste”:“sweet”,“tags”:[“fruit”,“red”,“sweet”]}
Carrot
{“taste”:“sweet”,“tags”:[“vegetable”,“orange”,“healthy”]}
Congratulations! You now know how to work with JSON arrays and objects in Anyquery (and most SQL databases).