Tomasz Barański <tomasz.baranski@posteo.net>
The db/neo4j module provides support for querying Neo4j database with Racket db module’s functions.
The following examples demonstrate how to connect to Neo4j and perform simple queries. The examples assume minimal familiarity with ‘db‘ and Neo4j.
First, we create a connection. Used without parameters, neo4j-connection connects to the default database without credentials.
Use query-exec to create some nodes.
Regular query can also be used. In this case the query statistics are returned, wrapped in simple-result struct.
(simple-result
'#hasheq((constraints_added . 0)
(constraints_removed . 0)
(contains_system_updates . #f)
(contains_updates . #t)
(indexes_added . 0)
(indexes_removed . 0)
(labels_added . 1)
(labels_removed . 0)
(nodes_created . 1)
(nodes_deleted . 0)
(properties_set . 1)
(relationship_deleted . 0)
(relationships_created . 0)
(system_updates . 0)))
The query string can include a number of Cypher statements.
"CREATE (john:Person {name: 'John'})""CREATE (joe:Person {name: 'Joe'})""CREATE (steve:Person {name: 'Steve'})""CREATE (sara:Person {name: 'Sara'})""CREATE (maria:Person {name: 'Maria'})""CREATE (john)-[:FRIEND]->(joe)-[:FRIEND]->(steve)""CREATE (john)-[:FRIEND]->(sara)-[:FRIEND]->(maria)")))(simple-result
'#hasheq((constraints_added . 0)
(constraints_removed . 0)
(contains_system_updates . #f)
(contains_updates . #t)
(indexes_added . 0)
(indexes_removed . 0)
(labels_added . 5)
(labels_removed . 0)
(nodes_created . 5)
(nodes_deleted . 0)
(properties_set . 5)
(relationship_deleted . 0)
(relationships_created . 4)
(system_updates . 0)))
The data can of course be queried.
> (query neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) RETURN john.name, fof.name")(rows-result '("john.name" "fof.name") '(#("John" "Maria") #("John" "Steve")))
Other functions are also supported.
> (query-rows neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) RETURN john.name, fof.name")'(#("John" "Maria") #("John" "Steve"))
> (query-row neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'St.*' RETURN john.name, fof.name")'#("John" "Steve")
'("Maria" "Steve")
> (query-value neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'St.*' RETURN fof.name")"Steve"
> (query-maybe-value neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'B.*' RETURN fof.name")#f
John's friend Sara's friend is Maria
John's friend Joe's friend is Steve
Queries can include parameters. You can either provide a hash with all params or list their values in the order in which they appear in the query. Keys of the hash must be symbols. When the same parameter occurs more then one time in the query, you must use a hash parameter
> (query-rows neo4j-c"MATCH (john {name: $name})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'St.*' RETURN john.name, fof.name"(hash 'name"John"))'(#("John" "Steve"))
> (query-rows neo4j-c"MATCH (john {name: $name})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'St.*' RETURN john.name, fof.name"#hash((name. "John")))'(#("John" "Steve"))
> (query-rows neo4j-c"MATCH (john {name: $name})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'St.*' RETURN john.name, fof.name""John")'(#("John" "Steve"))
Transactions are supported but with two limitations: only managed transaction can be used (i.e. those created with start-transaction or call-with-transaction ) and transaction cannot be nested.
> (query-exec neo4j-c"MATCH (bob:Person {name: 'Bob'}) MATCH (dave:Person {name: 'Dave'}) CREATE (dave)-[:FRIEND]->(bob)")"Bob"
'()
Prepared statemtents can be used, although they are handled completely at the client side, no resources are allocated at the server.
(prepare neo4j-c"MATCH (john {name: $name})-[:FRIEND]->()-[:FRIEND]->(fof) WHERE fof.name =~ 'St.*' RETURN john.name, fof.name"))'(#("John" "Steve"))
'(#("John" "Steve"))
For the obvious reason, list-tables and table-exists? are not supported.
list-tables: feature not supported
feature: listing tables
table-exists?: feature not supported
feature: listing tables
When using in-query , #:fetch parameter must always be set to +inf.0. Otherwise db will expect a cursor to be returned from query, and cursors are not supported.
neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) RETURN john.name, fof.name")])fof)'("Maria" "Steve")
neo4j-c"MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof) RETURN john.name, fof.name"#:fetch1)])fof)in-query: query did not return cursor
statement: "MATCH (john {name:
'John'})-[:FRIEND]->()-[:FRIEND]->(fof) RETURN john.name,
fof.name"
procedure
#:portport#:databasedatabase#:useruser#:passwordpassword