Optional traversals
Optional traversals in J1QL allow for the inclusion of related assets in query results, marked by wrapping a portion of the query with ({query_portion})?
. This feature enables combining entities from graph traversals and applying additional constraints.
FIND User
(THAT IS Person)?
In the above example, we search for User
entities and optionally traverse an IS
relationship to a Person
entity. If the relationship exists, the related Person
entities are added to the list of results.
Relationships can still be chained within an optional traversal:
The query below will return a list of Device
entities owned by a Person
that is a User
and User
assets that do not have an indirect relationship to the Device
.
FIND User
(THAT IS Person
THAT OWNS Device)?
Relationships that come after an optional traversal are processed on the combined results:
This query searches for Users
or UserGroups
that directly assigned an AccessPolicy
granting admin permissions to certain resources, or via an AccessRole
assigned to the User
/UserGroup
.
FIND (User|UserGroup)
(THAT ASSIGNED AccessRole)?
THAT ASSIGNED AccessPolicy
THAT ALLOWS AS permission *
WHERE permission.admin = true
RETURN TREE
Optional traversals can also be chained:
The combined results from each previous optional traversal will be used in the next optional traversal. The below query will find User
assets, Person
assets that have an IS
relationship to the User
and Device
assets that are owned by Person
and User
assets from the previous optional traversal.
FIND User
(THAT IS Person)?
(THAT OWNS Device)?
RETURN User, Person, Device
The optional traversals can also be aliased:
This allows entities to be used when returning results and when applying constraints. The following query illustrates aliasing an optional traversal.
FIND User
(THAT IS Person AS p)?
THAT OWNS Device AS d
WHERE p.email = "test@jupiterone.com"
RETURN p.displayName, d.displayName
Traversals performed within the ()?
function as normal graph traversals, so WITH
filters can still be applied to assist with narrowing results:
FIND User
(THAT IS Person WITH email = "test@jupiterone.com" AS p)?
THAT OWNS Device AS d
RETURN p.displayName, d.displayName
Historically it has been possible to use optional traversal aliasing to alias a union of entities. This behaviour was poorly defined and is deprecated from Feburary 2024.
Example:
FIND User
(THAT IS Person)? AS personOrUser
RETURN personOrUser.displayName, personOrUser._class