Traverse is a special command that retrieves the connected records crossing the relationships. This command works not only with graph API but at document level. This means you can traverse relationships between invoice and customers without the need to model the domain using the Graph API.
To know more look at Java-Traverse page.
In many cases SELECT can be used instead of TRAVERSE, resulting in faster and shorter query. Take a look at Should I use TRAVERSE or SELECT? |
TRAVERSE <[class.]field>|*|any()|all()
[FROM <target>]
[LET <Assignment>*]
WHILE <condition>
[LIMIT <max-records>]
[STRATEGY <strategy>]
$depth
where x is the maximum level of depth you want to reach. $depth is the first context variable that reports the depth level during traversal. NOTE: the old 'where' keyword is deprecatedAre the list of fields you want to traverse. If *
, any() or all() are specified then all the fields are traversed. This could be costly so to optimize the traverse use the pertinent fields. You can also specify fields at class level. Polymorphism is supported, so by specifying Person.city and Customer class extends Person, you will traverse Customer instances too.
Field names are case-sensitive, classes not.
Target can be:
Traverse command uses the following variables in the context:
#6:0.in.#5:0#.out
. You can also display it with -> select $path from (traverse ** from V)
Set<ORID>
.Assuming #10:1234 is the RID of the record to start traversing:
traverse * from #10:1234
In a social-network-like domain a profile is linked to all the friends. Below some commands.
Assuming #10:1234 is the RID of the record to start traversing get all the friends up to the third level of depth using the BREADTH_FIRST strategy:
traverse friends from #10:1234 while $depth <= 3 strategy BREADTH_FIRST
In case you want to filter per minimum depth create a predicate in the select. Example like before but excluding the first target vertex (#10:1234):
select from ( traverse friends from #10:1234 while $depth <= 3 ) where $depth >= 1
NOTE: You can also define the maximum depth in the SELECT clause but it's much more efficient to set it at the inner TRAVERSE statement because the returning record sets are already filtered by depth
Traverse command can be combined with SQL SELECT statement to filter the result set. Below the same example above but filtering by Rome as city:
select from ( traverse friends from #10:1234 while $depth <= 3 ) where city = 'Rome'
Another example to extract all the movies of actors that have worked, at least once, in any movie produced by J.J. Abrams:
select from (
traverse Movie.actors, Actor.movies from (
select from Movie where producer = "J.J. Abrams"
) while $depth <= 3
) where @class = 'Movie'
To return or use the current path in traversal refer to the $path variable:
select $path from ( traverse out from V while $depth <= 10 )
If traversing information, such as relationship names and depth level, are known at priori, please consider using SELECT instead of TRAVERSE. SELECT is faster on this case. Example:
This query traverses the "follow" relationship of Twitter accounts getting the 2nd level of friendship:
SELECT FROM (
TRAVERSE out('follow') FROM TwitterAccounts WHERE $depth <= 2
) WHERE $depth = 2
But can be expressed also with SELECT and it's shorter and faster:
SELECT out('follow').out('follow') FROM TwitterAccounts
Even if the TRAVERSE command can be used with any domain model, the place where is more used is the Graph-Database model.
Following this model all is based on the concepts of the Vertex (or Node) as the class "V" and the Edge (or Arc, Connection, Link, etc.) as the class "E". So if you want to traverse in a direction you have to use the class name when declare the traversing fields. Below the directions:
V.out, E.in
because vertices are connected with the "out" field but the edge exits as "in" field.V.in, E.out
because vertices are connected with the "in" field but the edge enters as "out" field.Example of traversing all the outgoing vertices found starting from the vertex with id #10:3434:
traverse V.out, E.in from #10:3434
So in a mailing-like domain to find all the messages sent in 1/1/2012 from the user 'Luca' assuming it's stored in the 'User' Vertex class and that messages are contained in the 'Message' Vertex class. Sent messages are stored as "out" connections of Edge class 'SentMessage':
select from (
traverse V.out, E.in from (
select from User where name = 'Luca'
) while $depth <= 2 and (@class = 'Message' || ( @class = 'SentMessage' and sentOn = '01/01/2012') )
) where @class = 'Message'
Before the introducing of TRAVERSE command OrientDB has the TRAVERSE operator but worked in the opposite way and it was applied in the WHERE condition.
TRAVERSE operator is deprecated. Please use the TRAVERSE command together with SELECT command to have much more power!
The syntax of the old TRAVERSE operator was:
SELECT FROM <target> WHERE <field> TRAVERSE[(<minDeep> [,<maxDeep> [,<fields>]])] (<conditions>)
WARNING: THIS SYNTAX WILL NOT BE SUPPORTED ANYMORE IN v. 2.1 |
Where:
Example of a query that returns all the vertices that have at least one friend (connected with out), up to the 3rd degree, that lives in Rome:
select from Profile where any() traverse(0,3) (city = 'Rome')
This can be rewritten using the most power TRAVERSE command:
select from Profile
let $temp = (
select from (
traverse * from $current while $depth <= 3
)
where city = 'Rome'
)
where $temp.size() > 0
Vertex edge Vertex User----->Friends----->User Label='f'
select distinct(in.lid) as lid,distinct(in.fid) as fid from (traverse V.out, E.in from #10:11 while $depth <=1) where @class='Friends'
SELECT distinct(in.lid) as lid, distinct(in.fid) as fid FROM (
TRAVERSE V.out, E.in FROM #10:11 WHILE $depth <=3
) WHERE @class='Friends'
To know more about other SQL commands look at SQL commands.