In MariaDB, JSON_SEARCH()
is a built-in function that allows you to get the path to a given value in a JSON document.
It accepts the JSON document and a string as arguments, and returns the path to the given string within the document.
Syntax
The syntax goes like this:
JSON_SEARCH(
json_doc,
return_arg,
search_str[, escape_char[, path] ...]
)
Where:
json_doc
is the JSON document andsearch_str
is the string.return_arg
is the keywordone
orall
. If you useone
, only the first path is returned. Any other occurrences are ignored. Which path is considered “first” is undefined (according to the MariaDB documentation). Ifall
is specified, the paths of all occurrences are returned. If there are multiple paths, they’re auto-wrapped as an array.- The
escape_char
argument is an optional character to use as an escape character. - The
path
argument is an optional argument to determine where the “top-level” path starts within the JSON document.
Example
Here’s an example to demonstrate:
SET @json = '
{
"name" : "Wag",
"type" : "Dog"
}';
SELECT JSON_SEARCH(@json, 'one', 'Wag');
Result:
+----------------------------------+ | JSON_SEARCH(@json, 'one', 'Wag') | +----------------------------------+ | "$.name" | +----------------------------------+
Here’s an example of returning the path for an element in an array:
SET @json = '
{
"product" : "Left Handed Screwdriver",
"sizes" : [ "Small", "Medium", "Large" ],
}';
SELECT JSON_SEARCH(@json, 'one', 'Medium');
Result:
+-------------------------------------+ | JSON_SEARCH(@json, 'one', "Medium") | +-------------------------------------+ | "$.sizes[1]" | +-------------------------------------+
Arrays are zero-based, and so $.sizes[1]
refers to the second element in the array.
Multiple Occurrences
If you want to return all paths that contain the string, use all
instead of one
for the second argument.
SET @json = '[
{ "name": "Wag", "type": "Dog", "weight": 20 },
{ "name": "Bark", "type": "Dog", "weight": 10 },
{ "name": "Meow", "type": "Cat", "weight": 7 }
]';
SELECT JSON_SEARCH(@json, 'all', 'Dog');
Result:
+----------------------------------+ | JSON_SEARCH(@json, 'all', "Dog") | +----------------------------------+ | ["$[0].type", "$[1].type"] | +----------------------------------+
If we change all
to one
, here’s what happens:
SET @json = '[
{ "name": "Wag", "type": "Dog", "weight": 20 },
{ "name": "Bark", "type": "Dog", "weight": 10 },
{ "name": "Meow", "type": "Cat", "weight": 7 }
]';
SELECT JSON_SEARCH(@json, 'one', 'Dog');
Result:
+----------------------------------+ | JSON_SEARCH(@json, 'one', "Dog") | +----------------------------------+ | "$[0].type" | +----------------------------------+
Only one path is returned.
Specify a Path
Here’s an example that specifies a path for which to search within the document:
SET @json = '
{
"_id" : 1,
"name" : "Wag",
"details" : {
"type" : "Dog",
"weight" : 20,
"awards" : {
"NZ Dog Award" : "Top Dog",
"New York Marathon" : "Fastest Animal",
"Sumo 2021" : "Biggest Dog"
}
}
}
';
SELECT JSON_SEARCH(
@json,
'all',
'%dog%',
NULL,
'$.details.awards'
) AS Result;
Result:
+-----------------------------------------------------------------+ | Result | +-----------------------------------------------------------------+ | ["$.details.awards.NZ Dog Award", "$.details.awards.Sumo 2021"] | +-----------------------------------------------------------------+
In this case, the string dog
actually occurs three times within the document, but only twice below the specified path.
Also, we used NULL
for the escape character argument, which results in the default escape character being used, which is the backslash (\
).
Default Escape Character
By default, the escape character is a backslash (\
).
Example:
SET @json = '[
{ "uid": "Wag", "pwd": "my%pwd" },
{ "uid": "Bark", "pwd": "my%%%pwd" },
{ "uid": "Bark", "pwd": "myBIGpwd" }
]';
SELECT
JSON_SEARCH(@json, 'all', 'my%pwd') AS "Not Escaped",
JSON_SEARCH(@json, 'all', 'my\%pwd') AS "Escaped";
Result:
+--------------------------------------+------------+ | Not Escaped | Escaped | +--------------------------------------+------------+ | ["$[0].pwd", "$[1].pwd", "$[2].pwd"] | "$[0].pwd" | +--------------------------------------+------------+
The percentage sign (%
) is a wildcard character that matches any number of characters. Therefore, if we don’t escape it, then it will match any number of characters, including characters that are not percentage signs.
But when we escape the percentage sign with the escape character, it will only match when there is exactly one percentage sign in that location.
The above results reflect this.
Specify a Custom Escape Character
You can specify a custom escape character if required. To do this, provide it as the fourth argument.
Example:
SET @json = '[
{ "uid": "Wag", "pwd": "my%pwd" },
{ "uid": "Bark", "pwd": "my%%%pwd" },
{ "uid": "Bark", "pwd": "myBIGpwd" }
]';
SELECT
JSON_SEARCH(@json, 'all', 'my%pwd', '!') AS "Not Escaped",
JSON_SEARCH(@json, 'all', 'my!%pwd', '!') AS "Escaped";
Result:
+--------------------------------------+------------+ | Not Escaped | Escaped | +--------------------------------------+------------+ | ["$[0].pwd", "$[1].pwd", "$[2].pwd"] | "$[0].pwd" | +--------------------------------------+------------+
So we get the same result as in the previous example. The only difference is that we specified a different escape character. In this case, we specified that the exclamation mark (!
) is the escape character.
Null Arguments
If any of the search string, search string, or path arguments are NULL
, the result is NULL
:
SELECT
JSON_SEARCH(null, 'all', 's', '', '$') AS a,
JSON_SEARCH('{"a":1}', 'all', null, '', '$') AS b,
JSON_SEARCH('{"a":1}', 'all', 's', '', null) AS c;
Result:
+------+------+------+ | a | b | c | +------+------+------+ | NULL | NULL | NULL | +------+------+------+
Incorrect Parameter Count
Providing no arguments results in an error:
SELECT JSON_SEARCH();
Result:
ERROR 1582 (42000): Incorrect parameter count in the call to native function 'JSON_SEARCH'
It’s the same when you provide too few arguments:
SELECT JSON_SEARCH('{"a":1}', 'all');
Result:
ERROR 1582 (42000): Incorrect parameter count in the call to native function 'JSON_SEARCH'