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.