HarperDB automatically indexes all top level attributes in a row / object written to a table. However, any attributes which holds JSON does not have its nested attributes indexed. In order to make searching and/or transforming these JSON documents easy, HarperDB offers a special SQL function called SEARCH_JSON. The SEARCH_JSON function works in SELECT & WHERE clauses allowing queries to perform powerful filtering on any element of your JSON by implementing the JSONata library into our SQL engine.
SEARCH_JSON(expression, attribute)
Executes the supplied string expression against data of the defined top level attribute for each row. The expression both filters and defines output from the JSON document.
Here are two records in the database:
Here is a simple query that gets any record with "Harper" found in the name.
The purpose of this query is to give us every movie where at least two of our favorite actors from Marvel films have acted together. The results will return the movie title, the overview, release date and an object array of the actor’s name and their character name in the movie.
Both function calls evaluate the credits.cast attribute, this attribute is an object array of every cast member in a movie.
A sample of this data from the movie The Avengers looks like
Let’s break down the SEARCH_JSON function call in the SELECT:
The first argument passed to SEARCH_JSON is the expression to execute against the second argument which is the cast attribute on the credits table. This expression will execute for every row. Looking into the expression it starts with “$[…]” this tells the expression to iterate all elements of the cast array.
Then the expression tells the function to only return entries where the name attribute matches any of the actors defined in the array:
So far, we’ve iterated the array and filtered out rows, but we also want the results formatted in a specific way, so we’ve chained an expression on our filter with: {“actor”: name, “character”: character}. This tells the function to create a specific object for each matching entry.
Sample Result
Just having the SEARCH_JSON function in our SELECT is powerful, but given our criteria it would still return every other movie that doesn’t have our matching actors, in order to filter out the movies we do not want we also use SEARCH_JSON in the WHERE clause.
This function call in the WHERE clause is similar, but we don’t need to perform the same transformation as occurred in the SELECT:
As seen above we execute the same name filter against the cast array, the primary difference is we are wrapping the filtered results in $count(…). As it looks this returns a count of the results back which we then use against our SQL comparator of >= 2.
To see further SEARCH_JSON examples in action view our Postman Collection that provides a sample schema & data with query examples: https://api.harperdb.io/
To learn more about how to build expressions check out the JSONata documentation: http://docs.jsonata.org/overview