So up until now we've been calculating path length based on the number of hops between our beginning node and our end node. This is roughly equivalent to counting the number of towns between one town and another town. But it doesn't really get at the value that is usually of greatest importance to us. And that is the actual distance between one location and another location. Which is found in the values that we've assigned to the edges between the nodes. So in this next example, we're going to perform that kind of a calculation. So the first two lines of code we're already fairly familiar with. We're matching a path between node a and node c, where the first node is H, and the second node is P. And this third line of code is also fairly familiar. We're extracting the names of the nodes and the path that's been returned, and we're returning a listing of those names as well as a length of the path. All of that is being returned as the variable pathLength. We've added a third element to our return statement, and that is using the reduce statement. So what we're doing here is, the purpose of the reduce statement, takes a set of values and reduces them down to a single value. So in this line of code we begin by setting a variable s equal to 0. And then we define a variable E, which represents the set of relationships in a path that's returned, or in other words, the edges. And we pass that into this variable s, and add to it, the value of the distance that we've assigned to that edge. So we're performing an aggregate calculation. And returning the final results to a variable called pathDist. And we're limiting that results to a single value. And so when we do this, we should get a value that is more indicative of the actual distance between our source and our destination. And so here's the results. The path itself, as we know, begins in H and ends in P. And it has a pathLength of 7, but it has a pathDist of 39. So we could interpret this to mean that even though there are 6 towns between the source town and the destination town, or a pathLength of 7, the actual distance in miles would be a value of 39. So with that we can apply Dijkstra's algorithm. So here I'm going to match the node with the name A, and the node with the name P. And we're going to find the shortest path in terms of hops from A to P. And we'll set that equal to the variable path. Then we'll perform a reduce command, and set the variable dist = 0. And we'll go through, and sum all of the distances of each of the edges in our shortest path. And return that value as a distance. And we'll also return the path variable. So remember, this is not the path in our network with the least weights. It is the weight of the shortest path based on numbers of hops. Now that's an inherent feature of the shortest path command in Cipher. So here is the path that's returned. It's a five node path with four edges and the total sum of the weights of those edges sums to a value of 22. So in our previous query, we specified that we wanted a match for the source node and the destination node. But if I don't specify my destination node, I can apply Dijkstra's single source shortest path algorithm from node A to any other node. So when we apply this query, the results displayed consist of the actual original path from A to P with a distance of 22. And we'll see a display of all of the intermediate paths generated in the process, all the way down to a single edge path between A and C. So just to reiterate, what we've calculated is the shortest hop path with the weights added, the sum of the weights of the edges in that path. This is not the least weight path of the entire network. Okay, so let's switch gears for a moment. As we learned in one of our previous lectures, we can extract a subset of nodes and edges from a particular graph for various reasons. Let's say for example that we want to avoid a particular town or a particular area where there might be congestion. And this would be represented by one of our nodes. So we're going to perform a similar match as we've done in the past, where we're going to match any node n with any node m, with a two edge between them. But we want to apply an additional constrained in which none of the n nodes are going to include the node D. And none of the m nodes are going to include the node D as well. And then we'll return the resulting graph. So when we do that, we get a graph but looks very much as we might expect. Very similar to our previous graph, but it is missing node D, so it only has ten nodes and it's now been reduced to ten edges. So now let's say we want to calculate the shortest path over there graph that we just returned in the previous query. So in this case, we're going to match the shortest path between node A and node P. But in the second line, we want to issue sort of a negative statement in which the resulting list of node names that we extract using the extract statement cannot contain the node D. And then we'll return that path and the length of that path. So when we issue this command, here's our resulting path. It's a five node path of length four. As we recall from one of our earlier queries where we were trying to calculate all of the shortest paths, we returned two paths. One path that contained D, and this is the second path, which did not contain D. So we can make this a little complicated. Instead of avoiding a single node in our resulting path, we're looking for a graph that doesn't contain the immediate neighborhood of a specific node. This means all of the nearest, or the first neighbors of a specific node. So in this case we're going to match the same node D, and all edges between D, and any other node. And then we are going to issue a collect command to collect all of the distinct neighbors of D. And we'll apply a constraint to that, in which the returned list of neighbors cannot contain the node with the name D. Likewise, the neighbors list for the target nodes, can also not contain the node D. And when we submit this command, we see a network that looks like this. Five nodes and four edges. And that seems to makes sense. Node D isn't in the network, nor are its first neighbors. But if you recall the original network, there may be a peculiar result that you might find a little bit disconcerting. So let's look at our original network. Now here's the node D, and here are all it's nearest neighbors. So these are the forbidden neighbors that we want to remove from our resulting graph. And we seemed to have done that successfully. These are the five nodes that are retained in the resulting graph, but there's a node out here. The node p, which seems to be neglected or not handled in the results. It's not a first neighbor of D. So it, in some ways arguably should be returned in our results, but it's not part of the connected graph that we saw returned. This is one area in which Cipher does not handle these situations by default. So we'll need to supplement our query with an additional query. In this case, the node P was a leaf node, so we want to make sure that not only matching the nodes that conform to these constraints above. But we also want to include the node or any nodes which are leaf nodes, which may also be arguably part of the results that you expect to be returned. Now in our network, we do have one root node, but it doesn't impact the results in this particular query. In the interests of being complete, for any network, most networks being much more complex than the one we're working with. We'd want to take into account not only those leaf nodes that might be left out, but also any root notes that might be left out. And finally, our last query example extends the previous query to find the graph which doesn't contain a selective neighborhood, in this case, the two neighborhood of a particular node. In this example we're going to use the node F. And we want to eliminate all of the second neighbors of that node. So initially we match all of those nodes that are second neighbors of F, including F itself. And we'll place those in a variable called MyList. Then we go back through the network and match all of the nodes and edges, where the source nodes are not part of the nodes in the MyList and the target nodes are not contained in MyList. And then we return those nodes and edges. And here's the resulting graph. It does not contain F or its first or second neighbors. If we scroll down to look at the original graph, here's node F, nodes H, J, C, A and L are all the first and second neighbors of F. So those should be eliminated from the graph that gets returned from our results. And sure enough, this subset of nodes represents the results that were returned from our query. It consists of nodes B, D, E, G, and P. And so this concludes our review of some of the more advanced path analytics queries. We were using a simple network, but we're providing additional data sets that are much larger and present a more realistic challenge in applying pathanalythics queries.