NAME
Neo4j::Cypher::Abstract - Generate Cypher query statements
SYNOPSIS
DESCRIPTION
When writing code to automate database queries, sometimes it is convenient to use a wrapper that generates desired query strings. Then the user can think conceptually and avoid having to remember precise syntax or write and debug string manipulations. A good wrapper can also allow the user to produce query statements dynamically, hide dialect details, and may include some simple syntax checking. SQL::Abstract
is an example of a widely-used wrapper for SQL.
The graph database Neo4j allows SQL-like declarative queries through its query language Cypher. Neo4j::Cypher::Abstract
is a Cypher wrapper in the spirit of SQL::Abstract
that creates very general Cypher productions in an intuitive, Perly way.
Basic idea : stringing clauses together with method calls
A clause is a portion of a complete query statement that plays a specific functional role in the statement and is set off by one or more reserved words. Clauses in Cypher include reading (e.g., MATCH), writing (CREATE), importing (LOAD CSV), and schema (CREATE CONSTRAINT) clauses, among others. They have arguments that define the clause's scope of action.
Cypher::Abstract objects possess methods for every Cypher clause. Each method adds its clause, with arguments, to the object's internal queue. Every method returns the object itself. When an object is rendered as a string, it concatenates its clauses to yield the entire query statement.
These features add up to the following idiom. Suppose we want to render the Cypher statement
MATCH (n:Users) WHERE n.name =~ 'Fred.*' RETURN n.manager
In Cypher::Abstract
, we do
$s = Neo4j::Cypher::Abstract->new()->match('n:Users')
->where("n.name =~ 'Fred.*'")->return('n.manager');
print "$s;\n"; # "" is overloaded by $s->as_string()
Because you may create many such statements in a program, a short alias for the constructor can be imported, and extra variable assignments can be avoided.
use Neo4j::Cypher::Abstract qw/cypher/;
use DBI;
my $dbh = DBI->connect("dbi:Neo4p:http://127.0.0.1:7474;user=foo;pass=bar");
my $sth = $dbh->prepare(
cypher->match('n:Users')->where("n.name =~ 'Fred.*'")->return('n.manager')
);
$sth->execute();
...
Patterns
Patterns are representations of subgraphs with constraints that are key components of Cypher queries. They have their own syntax and are also amenable to wrapping. In the example above, match()
uses a simple built-in shortcut:
$s->match('n:User') eq $s->match('(n:User)')
where (n:User)
is the simple pattern for "all nodes with label 'User'". The module Neo4j::Cypher::Pattern handles complex and arbitrary patterns. It is loaded automatically on use Neo4j::Cypher::Abstract
. Abstract patterns are written in a similar idiom as Cypher statements. They can be used anywhere a string is allowed. For example:
use Neo4j::Cypher::Abstract qw/cypher ptn/;
ptn->N(':Person',{name=>'Oliver Stone'})->R("r>")->N('movie') eq
'(:Person {name:'Oliver Stone'})-[r]->(movie)'
$sth = $dbh->prepare(
cypher->match(ptn->N(':Person',{name=>'Oliver Stone'})->R("r>")->N('movie'))
->return('type(r)')
);
See Neo4j::Cypher::Pattern for a full description of how to specify patterns.
WHERE clauses
As in SQL, Cypher has a WHERE clause that is used to filter returned results. Rather than having to create custom strings for common WHERE expressions, SQL::Abstract provides an intuitive system for constructing valid expressions from Perl data structures made up of hash, array, and scalar references. Neo4j::Cypher::Abstract contains a new implementation of the SQL::Abstract expression "compiler". If the argument to the where()
method (or any other method, in fact) is an array or hash reference, it is interpreted as an expression in SQL::Abstract style. (The parser is a complete reimplementation, so some idioms in that style may not result in exactly the same productions.)
Parameters
Parameters in Cypher are named, and given as alphanumeric tokens prefixed (sadly) with '$'. The Cypher::Abstract
object collects these in the order they appear in the complete statement. The list of parameters can be recovered with the parameters()
method.
$c = cypher->match('n:Person')->return('n.name')
->skip('$s')->limit('$l');
@p = $c->parameters; # @p is ('$s', '$l') /;
METHODS
Reading clauses
Writing clauses
- create(@ptns), create_unique($ptn)
- merge(@ptns)
- foreach($running_var => $list, cypher-><update statement>)
- set()
- delete(), detach_delete()
- on_create(), on_match()
Modifiers
General clauses
- return(@items), return_distinct(@items)
- with(@identifiers), with_distinct(@identifiers)
- unwind($list => $identifier)
- union()
- call()
- yield()
Hinting
Loading
Schema
- create_constraint_exist($node => $label, $property),create_constraint_unique($node => $label, $property)
- drop_constraint(...)
- create_index($label => $property), drop_index($label => $property)
Utility Methods
- parameters()
-
Return a list of statement parameters.
- as_string()
-
Render the Cypher statement as a string. Overloads
""
.
SEE ALSO
REST::Neo4p, DBD::Neo4p, SQL::Abstract
AUTHOR
Mark A. Jensen
CPAN: MAJENSEN
majensen -at- cpan -dot- org
COPYRIGHT
(c) 2017 Mark A. Jensen