Loops

Due to the nature of the Cypher queries, usually, you won't need something like a loop used in other programming languages. In fact, as you have probably already realized, the general structure of a Cypher query is formed by three phases and each one of these is optional. The phases are as follows:

  • Read: This is the phase where you read data from the graph using the START, MATCH, or OPTIONAL MATCH clauses.
  • Write: This is the phase where you modify the graph using CREATE, MERGE, SET, and all the other clauses we learned in this chapter.
  • Return: This is the phase where you choose what to return to the caller by using the RETURN clause. This part can be replaced by a WITH clause and then the query can start again from the read phase.

The read phase is important because the write phase will be executed for every item found in the read phase. For example, consider the following query:

MATCH (a:User {surname: "Roe"})
SET a.place = "London"
RETURN a

In this query, the SET command will be executed once for each node found with the MATCH clause. Consequently, you usually won't need an explicit for-loop statement.

Working with collections

The unique case when you need to iterate is when you work with collections. In the previous chapter, we saw that Cypher can use different kinds of collections: collections of nodes, relationships, and properties. Sometimes, you may need to iterate on a collection and perform some write operation consequently. There is a clause for this purpose, and it is the FOREACH clause. Its syntax is akin to the syntax of collection clauses we learned in the previous chapters. The syntax is as follows:

FOREACH (variable IN collection | command)

Let's see it in action with an example. Suppose that in our social network, you want a function that traverses the shortest path from one user to another and creates a new relationship of the type MaybeKnows between each node visited and the first user. Does it sound difficult to achieve this with a single query? No, it can be done with just two clauses: a MATCH clause and a FOREACH clause, as shown in the following query:

MATCH p=shortestPath( 
   (a:User {name: "Mary", surname: "Smith"})-[*]-
       (b:User {name: "Jane", surname: "Jones"}) ) 
FOREACH (n IN tail(nodes(p)) | 
   CREATE UNIQUE (n)-[:MaybeKnows]->(a))

In the first step, this query computes the shortest path between the two nodes, using the pattern we learned in Chapter 1, Querying Neo4j Effectively with Pattern Matching. Then, there is an iteration over all the nodes, except for the first node; for each node, a unique relation is created between the first node of the path (Mary Smith) and itself. Now, let's take a look at the content of the FOREACH clause, that is, tail(nodes(p)). The function nodes extracts all the nodes of the path, while the tail function returns all the items except for the first of a collection. In this case, we use the tail function because we don't want Cypher to create a relation between the user node Mary Smith and itself. In fact, Neo4j allows you to create self-loops. Self-loops are relations between a node and itself. Note that using self-loops is perfectly right in some contexts but not in this case. So, we have avoided it by using the tail function.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.21.47