Traversal

Content in Cloud CMS is stored in a graph-like structure that consists of nodes and associations. Nodes are entities
in the graph and associations are the relationships (the lines between points in the graph).

As such, when working with content in Cloud CMS, you'll often find it useful to employ these structures in terms of
your content model. Your content can be spread out between nodes and associations equally so that both the entities
and the relationships hold JSON properties that are of interest from a query and search perspective. You may choose
to query one or the other at runtime to determine things about your content structure (indeed, the query and search
engines work equivalently well for both nodes and associations as both are thought of as first class citizens).

Traversals offer a way for you to walk the graph of the relationships to find content that fits a certain shape
within the graph. In essence, they provide a way for you to describe a starting point and a distance away from that
starting point in terms of discovering matching nodes to return in the result set.

One analogy for traversals might be a geographical one. Suppose you were looking for restaurants and you wanted to
find someplace that sold chinese food. You could open the phone book and you'd find a lot of places. But you might
want to further specify things so as to say, "I want Chinese food that is 1 minute driving or less from 27th Street
and Grange Avenue in Greenfield, Wisconsin". Now you're doing a traversal. You start at that location and then
look for places around it that match that constraint.

And you find the House of Fong. (Editor's Note: They had good egg rolls when I was a kid)

When talking about traversals in the Content Graph, the concept is similar. The only difference is that you think
of distance as the number of "hops" away from a node (which is to say, the depth or the number of
associations you need to move away from a node before it's considered too far away).

Traversals let you describe the depth as well as the kind of relationships (i.e. the association type) to travel
along. They also let you describe the kinds of content to hand back. With traversals, you generally describe
the "shape" of the space you're looking in and how to detect matches based on content type.

Permissions

As with everything Cloud CMS, the traversal API respects the underlying permissions and authorities that have been granted
to the objects that are considered result candidates. Authorities are checked before content is retrieved which means
that two people could execute the same traversal and get different results.

Permissions are baked into Cloud CMS all the way down to the core. If you need to get back the full set of content
objects for purposes of synchronization or anything else, make sure that you have sufficient authorities to do so.

Traversal API

The Traversal REST API assumes a repository and branch that identifies where your content lives. It also requires
a starting node from which the traversal begins.

POST /repositories/{repositoryId}/branches/{branchId}/nodes/{nodeId}/traverse

The content type should be application/json and the JSON payload should look like this:

{
    "associations": {
        "a:child": "ANY",
        "a:knows": "INCOMING",
        "a:related": "OUTGOING"
    },
    "depth": 2,
    "types": [ 
        "custom:type1", 
        "custom:type2" 
    ]
}

The associations tells Cloud CMS how to deal with associations that are candidates to be traversed.
When an association is encountered, this block tells Cloud CMS when to traverse it (such as when the association is
an outgoing association, or when it's incoming, or either way).

The depth number tells Cloud CMS how many hops away from the starting point to traverse.

Finally, the types array indicates the kinds of nodes to hand back.

You can also set:

  • order - the search order - either BREADTH_FIRST or DEPTH_FIRST.
  • filter - nodes to be included - either ALL or ALL_BUT_START_NODE.

Response

The response comes back in a structure like this:

{
    "node": "{nodeId}",
    "config": {},
    "node_count": 0,
    "nodes": {},
    "association_count": 0,
    "associations": {}
}

All of the discovered node come back in the nodes block. If you specified node types, this block
will be constrained only to nodes of that type. The associations come back in the associations
block. This will consist of any associations that were successfully traversed and may be constrained by
any association types you provide.

Note that the response does not come back in a tree structure and that it does not support pagination. To
enable pagination, please refer to the
composite find function which allows you to mix traversal
with search and query. This also allows you to paginate responses.

Example Payloads

Here is an example where we find all nodes that are 1 hop away from a given node. The filter
attribute can be used to describe filters that should be applied to the traversal. By default, the filter
is ALL which indicates to include all nodes, including the start node.

{
    "depth": 1
}

Here is an example where we find all nodes that are 1 hop away from a given node. In this case, we set the
filter to ALL_BUT_START_NODE to have it exclude the start node from the result set.

{
    "depth": 1,
    "filter": "ALL_BUT_START_NODE"
}

Here is an example where we search for nodes that are 2 hops away. We only want nodes to come back that are of
type my:article. The lookup order is BREADTH_FIRST by default.

{
    "depth": 2,
    "types": ["my:article"]
}

We can also instruct the traversal to use a DEPTH_FIRST traversal order. This will alter the
order of items in the result set and can be useful from a pagination perspective, depending on the order that your
users will expect items to appear.

{
    "depth": 2,
    "types": ["my:article"],
    "order": "DEPTH_FIRST"
}

Combining Traversal with Search and Query

For information on mixing traversals with search and query, please take a look at
the documentation on Find.