Skip to content

Neo4j::Cypher Start

andreasronge edited this page Oct 1, 2012 · 12 revisions

Every query describes a pattern, and in that pattern one can have multiple start points. A start point is a relationship or a node that form the starting points for a pattern match. You can either introduce start points by id, or by index lookups.

In Neo4j::Core and Neography (with the neo4j-cypher adapter) you can also give the start nodes as ruby arguments for the DSL Example:

Neo4j.query(Person.find_by_name('andreas')) {|me| me > ':friends' > node(:myfriends).ret})

See also the Neo4j Documetation.

Node By Id

Binding a node as a start point can be done with the node method.

Example:

node(3)

Will generate START v0=node(3) RETURN v0. Remember that the last value evaluated will be the return value (when possible).

Variable Names

As shown in the example above the DSL will automatically create a new variable, v0. There is a #as method which allows you to specify the variable name. The #as method is available on nodes, relationships, functions (like count) and paths.

Example:

node(3).as(:x)

Will generate START x = node(3) RETURN x

Variables

Nodes and Relationships can also be used in WHERE and MATCH clauses. To express that you want any node use the node or rel without any argument.

Example:

  node(3) <=> node

which is same as: START v1=node(1) MATCH v3 = (v1)--(v2) RETURN v3 The spaceship operator <=> means match any outgoing or incoming relationship.

The #as method can be used if you need to specify the name of the variable. Example:

  node(3) <=> node.as(:friends)

Which will instead generate the following string START v1=node(1) MATCH v2 = (v1)--(friend) RETURN v2

A shorter way of doing this is using ruby symbols:

  node(3) <=> node(:friends)

An even short way of doing this is using ruby symbols.

  node(3) <=> :friends

Start Relationship, #rel

The rel is normally used for matching purpose, but can also be used to specify a start relationship.

Example:

rel 1,2,3

Is the same as START v1=relationship(1,2,3) RETURN v1

Optional Relationship, #rel

The method rel with no arguments or the rel? method specifies an optional relationship.

Match any outgoing relationships from node 3:

 node(3) > rel > :person 

This is same as START v1=node(3) MATCH v2 = (v1)-[?]->(person) RETURN v2

Matching a Relationship Type, #rel

To match a relationship type is given as argument(s) for the rel method.

node(3) > rel(:friends) > node(:person)

Which is same as START v1=node(3) MATCH v2 = (v1)-[:`friends`]->(person) RETURN v2 Notice that the relationship type is escaped so that you can have white spaces etc as relationship types.

Multiple relationship types is simply specified by more arguments for the rel method. Example:

node(1) > rel(:friends, :work, :family) > node(:person)

Which will generate the following: 'START v1=node(1) MATCH v2 = (v1)-[:`friends`|`work`|`family`]->(person) RETURN v2'

This can also be combined with the #as method.

node(1) > rel(:friends, :work, :family).as(:foo) > node(:person)
ret :foo

Which will generate START v1=node(1) MATCH (v1)-[foo:`friends`|`work`|`family`]->(person) RETURN foo

Matching a Relationship with a Symbol

If a symbol is specified when an relationship is expected it will automatically be converted to a relationship. This means that instead of writing node(3) > rel(:r) > :person you can write:

node(3) > :r > :person

Matching a Relationship with a String

If a relationship is specified as a string it will be used in the match clause as is.

Example: Return the path from node 3 navigating outgoing relationship of type friend or type knows depth one.

node(3) > rel(':friend|knows') > 'bla'

Will generate START v1=node(3) MATCH v2 = (v1)-[:friend|knows]->(bla) RETURN v2

String will automatically be converted to a relationship pattern. This means that the example above can be written like this:

node(3) > ':friend|knows' > 'bla'

Relationship Identifiers

You can also use relationship as variables. Let say you want to return all the relationships instead from the query above. This can be done like this:

node(3) > rel(':friend|knows').as(:foo) > :person

Which is the same as START v1=node(3) MATCH v2 = (v1)-[foo:friend|knows]->(person) RETURN v2 This allows you to identify an relationship, which for example can be used later as a return value.

Example:

node(3) > rel(':friend|knows').as(:foo) > :person
ret :foo

Which is same as:

node(3) > rel(':friend|knows').as(:foo).ret > :person

Which will generate START v1=node(3) MATCH (v1)-[foo:friend|knows]->(person) RETURN foo See Neo4j::Cypher-Return

Relationship, #rel?

As a convenience method, use the rel? method to specify optional relationship. If the relationship is there, it is returned. If it’s not, nil is returned in it’s place.

For example: node 3 does not have any relationship of type knows

 node(3).ret > rel?(:knows).as(:k).ret > :person

Generates cypher: START v1=node(3) MATCH (v1)-[k?:knows]->(person) RETURN v1,k When the query is executed it will return a node, and null, since the node has no outgoing knows relationship.

Alternative, using the outgoing method:

node(3).as(:me).outgoing(rel?(:knows).as(:knows)).ret(:me, :knows)

Generates: START me=node(3) MATCH (me)-[knows?:`knows`]->(v1) RETURN me,knows

Index Lookup

Since you can inject your own nodes and relationship as argument to the Cypher DSL there is less needed to use the lookup and query methods.

Example of finding a single node using the lucene index 'myindex':

lookup('myindex', "desc", "A")
# same as "START n0=node:myindex(desc="A") RETURN n0"

Example of using the lucene query syntax:

query('myindex', "name:A")
# same as "START n0=node:myindex(name:A) RETURN n0])"

See query_rel and lookup_rel for lucene queries on relationships. Notice that if you use Neo4j::Core (or Neo4j::Rails) you can use the class instead of the string describing the name of the index, see Neo4j::Core-Cypher

Clone this wiki locally