Neo4j::Cypher

Alex Burkhart edited this page Jul 1, 2013 · 26 revisions
Clone this wiki locally

“Cypher” is a declarative graph query language that allows for expressive and efficient querying of the graph store without having to write traversals through the graph structure in code.

The neo4j-cypher gem makes it possible to generate Cypher query strings from Ruby DSLs. The cypher language is described here: Neo4j Cypher Documentation. See the RSpecs for more examples here or the Neo4j Cypher DSL blog

Content

  • API - The neo4j-cypher and neography cypher adaptor.
  • Start - Starting points in the graph: node, rel, query, lookup
  • Match - The graph pattern to match, bound to the starting points, e.g. outgoing, <=>
  • Where - Filtering criteria, e.g. &, ==
  • Return - What to return and aggregate, e.g. ret
  • Functions - Predicates, Scalar functions and Aggregated functions, e.g. any?, extract
  • Aggregation Cypher offers aggregation, much like SQL’s GROUP BY, e.g. count
  • Sorting Sorting desc, asc, skip and limit
  • With - Divides a query into multiple, distinct parts. Create, Delete, Update, e.g. with
  • Examples - Some examples

Why?

Why should I write my queries using the neo4j-cypher DSL instead of using original cypher syntax ?

My Answer 1 Better readablity for (ruby) programmers, which means easier to understand and write queries.

Why is the neo4j-cypher DSL more readable ?

For example: Find my friends I got since 1994 using the original cypher language:

START me=node(1) 
MATCH (me)-[friend_rel:`friends`]->(friends) 
WHERE (friend_rel.since = 1994) 
RETURN friends

Instead of relying on a strict order of the clauses (START, MATCH, WHERE ...) and having to use variables (me and friends) you can write it like this:

Neo4j.query do
  node(1).outgoing(rel(:friends).where{|r| r[:since] == 1994})
end

This is more or less plain english (for me), navigate from node(1) outgoing relationships friends where friends since property is equal 1994. Remember just like ruby, the last value evaluated is the return value which means it will return your friend.

Another way if you want to write it in many lines and using Ruby variables:

# user = User.find(1)
Neo4j.query(user) do |me|
  friend_rel = rel(:friends)
  friend = node
  match { me > friend_rel > friend }
  where { friend_rel[:since] == 1994 }
  ret friend
end

Or using > operator and flagging what to return with the ret method.

Neo4j.query{ node(1) > (rel(:friends)[:since] == 1994) > node.ret }

The Ruby DSL gives you the control how best to express queries using Ruby syntax.

Querying vs Inspecting

To perform a query, you wrap your query in a Neo4j.query block,

Neo4j.query(starting_nodes){|start| ...query... }
# => <#Neo4j::Cypher::ResultWrapper> # object with the query's results

You may inspect the Cypher Query string generated by the DSL using Neo4j::Cypher.query instead.

Neo4j::Cypher(starting) { |start| ...query... }
# => "START v1=node(1) RETURN v1;"  # your query as a generated Cypher string

Another Simple Example

Because it's a bit similar to the neo4j.rb syntax.

For example, counting my friends:

Neo4j.query{ node(1).outgoing(:friends).count }

Notice

  • The neo4j-cypher gem can be used both from neo4j.rb (see Neo4j::Core-Cypher) and from the Neo4j rest API, see neography
  • Both neography (Neography.execute_query) and neo4j-core (Neo4j.query) includes methods which also executes the query.