Query hierarchical data structures on Hasura with Postgres ltree
Introducing ltree
operator support in Hasura
What's ltree
?
- configuring permission rules in Hasura for a Customer Relationship Management tool.
- modelling employee reporting relationships, or a marketplace with sub/categories.
- validating filesystem paths or DNS records.
Exploring ltree
Project setup
- Set up a new project in Hasura Cloud 2.0 or higher with a Postgres database.
- Enable the extension and populate the Postgres database with a value for each label path. You can do this via the Data > SQL tab, as follows:
CREATE EXTENSION IF NOT EXISTS ltree;
CREATE TABLE test (path ltree);
INSERT INTO
test
VALUES
('Top'),
('Top.Science'),
('Top.Science.Astronomy'),
('Top.Science.Astronomy.Astrophysics'),
('Top.Science.Astronomy.Cosmology'),
('Top.Hobbies'),
('Top.Hobbies.Amateurs_Astronomy'),
('Top.Collections'),
('Top.Collections.Pictures'),
('Top.Collections.Pictures.Astronomy'),
('Top.Collections.Pictures.Astronomy.Stars'),
('Top.Collections.Pictures.Astronomy.Galaxies'),
('Top.Collections.Pictures.Astronomy.Astronauts');
-- Optionally, create indexes to speed up certain operations
CREATE INDEX path_gist_idx ON test USING GIST (path);
CREATE INDEX path_idx ON test USING BTREE (path);
- Visit the Explorer section of the API tab in your Hasura Cloud project. You should see
ltree
operators such as_ancestor
and_descendant
under thepath
filter options.
ltree
operators
_ancestor
query {
test(where: { path: { _ancestor: "Top.Collections.Pictures.Astronomy" } }) {
path
}
}
{
"data": {
"test": [
{
"path": "Top"
},
{
"path": "Top.Collections"
},
{
"path": "Top.Collections.Pictures"
},
{
"path": "Top.Collections.Pictures.Astronomy"
}
]
}
}
query {
test(where: { path: { _ancestor: "Top.Collections.Pictures." } }) {
path
}
}
{
"errors": [
{
"extensions": {
"path": "$.selectionSet.test.args.where.path._ancestor",
"code": "parse-failed"
},
"message": "Expecting label path: a sequence of zero or more labels separated by dots, for example L1.L2.L3"
}
]
}
_descendant
query {
test(where: { path: { _descendant: "Top.Collections.Pictures.Astronomy" } }) {
path
}
}
{
"data": {
"test": [
{
"path": "Top.Collections.Pictures.Astronomy"
},
{
"path": "Top.Collections.Pictures.Astronomy.Stars"
},
{
"path": "Top.Collections.Pictures.Astronomy.Galaxies"
},
{
"path": "Top.Collections.Pictures.Astronomy.Astronauts"
}
]
}
}
_matches
# Match any label path containing the node `Astronomy`
query {
test(where: { path: { _matches: "*.Astronomy.*" } }) {
path
}
}
{
"data": {
"test": [
{
"path": "Top.Science.Astronomy"
},
{
"path": "Top.Science.Astronomy.Astrophysics"
},
{
"path": "Top.Science.Astronomy.Cosmology"
},
{
"path": "Top.Collections.Pictures.Astronomy"
},
{
"path": "Top.Collections.Pictures.Astronomy.Stars"
},
{
"path": "Top.Collections.Pictures.Astronomy.Galaxies"
},
{
"path": "Top.Collections.Pictures.Astronomy.Astronauts"
}
]
}
}
_matches_fulltext
query {
test(where: { path: { _matches_fulltext: "Astro*%" } }) {
path
}
}
{
"data": {
"test": [
{
"path": "Top.Science.Astronomy"
},
{
"path": "Top.Science.Astronomy.Astrophysics"
},
{
"path": "Top.Science.Astronomy.Cosmology"
},
{
"path": "Top.Hobbies.Amateurs_Astronomy"
},
{
"path": "Top.Collections.Pictures.Astronomy"
},
{
"path": "Top.Collections.Pictures.Astronomy.Stars"
},
{
"path": "Top.Collections.Pictures.Astronomy.Galaxies"
},
{
"path": "Top.Collections.Pictures.Astronomy.Astronauts"
}
]
}
}
query {
test(where: { path: { _matches_fulltext: "Astro*% & !pictures@" } }) {
path
}
}
{
"data": {
"test": [
{
"path": "Top.Science.Astronomy"
},
{
"path": "Top.Science.Astronomy.Astrophysics"
},
{
"path": "Top.Science.Astronomy.Cosmology"
},
{
"path": "Top.Hobbies.Amateurs_Astronomy"
}
]
}
}
_any
variants
query {
test(
where: {
path: {
_ancestor_any: [
"Top.Collections.Pictures.Astronomy"
"Top.Science.Astronomy"
]
}
}
) {
path
}
}
{
"data": {
"test": [
{
"path": "Top"
},
{
"path": "Top.Science"
},
{
"path": "Top.Science.Astronomy"
},
{
"path": "Top.Collections"
},
{
"path": "Top.Collections.Pictures"
},
{
"path": "Top.Collections.Pictures.Astronomy"
}
]
}
}
Further resources
Related reading