The ActiveGraph::Core::Query
class gem defines a DSL which allows for easy creation of Neo4j Cypher queries. They can be started from a session like so:
a_session.query
# The current session for `Node` / `Relationship` in the `neo4j` gem can be retrieved with `ActiveGraph::Base.current_session`
Advantages of using the Query class include:
- Method chaining allows you to build a part of a query and then pass it somewhere else to be built further
- Automatic use of parameters when possible
- Ability to pass in data directly from other sources (like Hash to match keys/values)
- Ability to use native Ruby objects (such as translating nil values to IS NULL, regular expressions to Cypher-style regular expression matches, etc...)
Below is a series of Ruby code samples and the resulting Cypher that would be generated. These examples are all generated directly from the spec file and are thus all tested to work.
Ruby: | .match(n: [:Person, "Animal"])
|
Cypher: | MATCH (n:`Person`:`Animal`)
|
Ruby: | .match(n: 'Person {name: "Brian"}')
|
Cypher: | MATCH (n:Person {name: "Brian"})
|
Ruby: | .match(n: {name: 'Brian', age: 33})
|
Cypher: | MATCH (n {name: $n_name, age: {n_age}})
|
Parameters: {:n_name=>"Brian", :n_age=>33}
Ruby: | .match(n: {Person: {name: 'Brian', age: 33}})
|
Cypher: | MATCH (n:`Person` {name: $n_Person_name, age: $n_Person_age})
|
Parameters: {:n_Person_name=>"Brian", :n_Person_age=>33}
Ruby: | .match('(n)--(o)', '(o)--(p)')
|
Cypher: |
|
Ruby: | .match('(n)--(o)').match('(o)--(p)')
|
Cypher: |
|
Ruby: | .optional_match(n: Person)
|
Cypher: | OPTIONAL MATCH (n:`Person`)
|
Ruby: | .match('(m)--(n)').optional_match('(n)--(o)').match('(o)--(p)')
|
Cypher: | MATCH (m)--(n), (o)--(p) OPTIONAL MATCH (n)--(o)
|
Ruby: | .using('INDEX m:German(surname)')
|
Cypher: | USING INDEX m:German(surname)
|
Ruby: | .using('INDEX m:German(surname)').using('SCAN m:German')
|
Cypher: | USING INDEX m:German(surname) USING SCAN m:German
|
Parameters: {:q_age=>30}
Ruby: | .where('q.age' => [30, 32, 34])
|
Cypher: |
|
Parameters: {:q_age=>[30, 32, 34]}
Ruby: | .where('q.age IN $age', age: [30, 32, 34])
|
Cypher: |
|
Parameters: {:age=>[30, 32, 34]}
Ruby: | .where('(q.age IN $age)', age: [30, 32, 34])
|
Cypher: |
|
Parameters: {:age=>[30, 32, 34]}
Ruby: | .where('q.name =~ ?', '.*test.*')
|
Cypher: | WHERE (q.name =~ $question_mark_param)
|
Parameters: {:question_mark_param=>".*test.*"}
Ruby: | .where('(q.name =~ ?)', '.*test.*')
|
Cypher: | WHERE (q.name =~ $question_mark_param)
|
Parameters: {:question_mark_param=>".*test.*"}
Ruby: | .where('(LOWER(str(q.name)) =~ ?)', '.*test.*')
|
Cypher: | WHERE (LOWER(str(q.name)) =~ $question_mark_param)
|
Parameters: {:question_mark_param=>".*test.*"}
Ruby: | .where('q.age IN ?', [30, 32, 34])
|
Cypher: | WHERE (q.age IN $question_mark_param)
|
Parameters: {:question_mark_param=>[30, 32, 34]}
Ruby: | .where('q.age IN ?', [30, 32, 34]).where('q.age != ?', 60)
|
Cypher: | WHERE (q.age IN $question_mark_param) AND (q.age != $question_mark_param2)
|
Parameters: {:question_mark_param=>[30, 32, 34], :question_mark_param2=>60}
Ruby: | .where(q: {age: [30, 32, 34]})
|
Cypher: |
|
Parameters: {:q_age=>[30, 32, 34]}
Parameters: {:ID_q=>22}
Ruby: | .where(q: {age: 30, name: 'Brian'})
|
Cypher: | WHERE (q.age = $q_age AND q.name = $q_name)
|
Parameters: {:q_age=>30, :q_name=>"Brian"}
Ruby: | .where(q: {age: 30, name: 'Brian'}).where('r.grade = 80')
|
Cypher: | WHERE (q.age = $q_age AND q.name = $q_name) AND (r.grade = 80)
|
Parameters: {:q_age=>30, :q_name=>"Brian"}
Ruby: | .where(q: {name: /Brian.*/i})
|
Cypher: | WHERE (q.name =~ $q_name)
|
Parameters: {:q_name=>"(?i)Brian.*"}
Parameters: {:name=>"(?i)Brian.*"}
Ruby: | .where(name: /Brian.*/i).where(name: /Smith.*/i)
|
Cypher: | WHERE (name =~ $name) AND (name =~ $name2)
|
Parameters: {:name=>"(?i)Brian.*", :name2=>"(?i)Smith.*"}
Ruby: | .where(q: {age: (30..40)})
|
Cypher: | WHERE (q.age IN RANGE($q_age_range_min, $q_age_range_max))
|
Parameters: {:q_age_range_min=>30, :q_age_range_max=>40}
Ruby: | .where_not('q.age' => 30)
|
Cypher: | WHERE NOT(q.age = $q_age)
|
Parameters: {:q_age=>30}
Ruby: | .where_not('q.age IN ?', [30, 32, 34])
|
Cypher: | WHERE NOT(q.age IN $question_mark_param)
|
Parameters: {:question_mark_param=>[30, 32, 34]}
Ruby: | .where_not(q: {age: 30, name: 'Brian'})
|
Cypher: | WHERE NOT(q.age = $q_age AND q.name = $q_name)
|
Parameters: {:q_age=>30, :q_name=>"Brian"}
Ruby: | .where_not(q: {name: /Brian.*/i})
|
Cypher: | WHERE NOT(q.name =~ $q_name)
|
Parameters: {:q_name=>"(?i)Brian.*"}
Ruby: | .where('q.age > 10').where_not('q.age > 30')
|
Cypher: | WHERE (q.age > 10) AND NOT(q.age > 30)
|
Ruby: | .where_not('q.age > 30').where('q.age > 10')
|
Cypher: | WHERE NOT(q.age > 30) AND (q.age > 10)
|
Ruby: | .match_nodes(var: node_object)
|
Cypher: | MATCH (var) WHERE (ID(var) = $ID_var)
|
Parameters: {:ID_var=>246}
Ruby: | .optional_match_nodes(var: node_object)
|
Cypher: | OPTIONAL MATCH (var) WHERE (ID(var) = $ID_var)
|
Parameters: {:ID_var=>246}
Ruby: |
|
Cypher: | MATCH (var) WHERE (ID(var) = $ID_var)
|
Parameters: {:ID_var=>924}
Ruby: | .match_nodes(user: user, post: post)
|
Cypher: | MATCH (user), (post) WHERE (ID(user) = $ID_user) AND (ID(post) = $ID_post)
|
Parameters: {:ID_user=>246, :ID_post=>123}
Ruby: | .match_nodes(user: user, post: 652)
|
Cypher: | MATCH (user), (post) WHERE (ID(user) = $ID_user) AND (ID(post) = $ID_post)
|
Parameters: {:ID_user=>246, :ID_post=>652}
Ruby: | .unwind(x: [1,3,5]).unwind('val as y')
|
Cypher: | UNWIND [1, 3, 5] AS x UNWIND val as y
|
Ruby: | .return(q: [:name, :age], r: :grade)
|
Cypher: | RETURN q.name, q.age, r.grade
|
Ruby: | .return(q: [:neo_id, :prop])
|
Cypher: |
|
Ruby: | .order('q.age', 'q.name DESC')
|
Cypher: | ORDER BY q.age, q.name DESC
|
Ruby: | .order(q: [:age, {name: :desc}])
|
Cypher: | ORDER BY q.age, q.name DESC
|
Ruby: | .order(q: [:age, {neo_id: :desc}])
|
Cypher: | ORDER BY q.age, ID(q) DESC
|
Ruby: | .order(q: [:age, {name: :desc, grade: :asc}])
|
Cypher: | ORDER BY q.age, q.name DESC, q.grade ASC
|
Ruby: | .order(q: [:age, {name: :desc, neo_id: :asc}])
|
Cypher: | ORDER BY q.age, q.name DESC, ID(q) ASC
|
Ruby: | .order(q: {age: :asc, name: :desc})
|
Cypher: | ORDER BY q.age ASC, q.name DESC
|
Ruby: | .order(q: {age: :asc, neo_id: :desc})
|
Cypher: | ORDER BY q.age ASC, ID(q) DESC
|
Ruby: | .order(q: [:age, 'name desc'])
|
Cypher: | ORDER BY q.age, q.name desc
|
Ruby: | .order(q: [:neo_id, 'name desc'])
|
Cypher: | ORDER BY ID(q), q.name desc
|
Parameters: {:limit_3=>3}
Parameters: {:limit_3=>3}
Parameters: {:limit_3=>3, :limit_5=>5}
Parameters: {:skip_5=>5}
Parameters: {:skip_5=>5}
Parameters: {:skip_5=>5, :skip_10=>10}
Parameters: {:skip_6=>6}
Ruby: | .with('n.age AS age', 'count(n) as c')
|
Cypher: | WITH n.age AS age, count(n) as c
|
Ruby: | .with(['n.age AS age', 'count(n) as c'])
|
Cypher: | WITH n.age AS age, count(n) as c
|
Ruby: | .with_distinct('n.age AS age')
|
Cypher: | WITH DISTINCT n.age AS age
|
Ruby: | .with_distinct('n.age AS age', 'count(n) as c')
|
Cypher: | WITH DISTINCT n.age AS age, count(n) as c
|
Ruby: | .with_distinct(['n.age AS age', 'count(n) as c'])
|
Cypher: | WITH DISTINCT n.age AS age, count(n) as c
|
Ruby: | .with_distinct(age: 'n.age')
|
Cypher: | WITH DISTINCT n.age AS age
|
Ruby: | .create(age: 41, height: 70)
|
Cypher: | CREATE ( {age: $age, height: $height})
|
Parameters: {:age=>41, :height=>70}
Ruby: | .create(Person: {age: 41, height: 70})
|
Cypher: | CREATE (:`Person` {age: $Person_age, height: $Person_height})
|
Parameters: {:Person_age=>41, :Person_height=>70}
Ruby: | .create(q: {Person: {age: 41, height: 70}})
|
Cypher: | CREATE (q:`Person` {age: $q_Person_age, height: {q_Person_height}})
|
Parameters: {:q_Person_age=>41, :q_Person_height=>70}
Ruby: | .create(q: {Person: {age: nil, height: 70}})
|
Cypher: | CREATE (q:`Person` {age: $q_Person_age, height: {q_Person_height}})
|
Parameters: {:q_Person_age=>nil, :q_Person_height=>70}
Ruby: | .create(q: {:'Child:Person' => {age: 41, height: 70}})
|
Cypher: | CREATE (q:`Child:Person` {age: $q_Child_Person_age, height: {q_Child_Person_height}})
|
Parameters: {:q_Child_Person_age=>41, :q_Child_Person_height=>70}
Ruby: | .create(:'Child:Person' => {age: 41, height: 70})
|
Cypher: | CREATE (:`Child:Person` {age: $Child_Person_age, height: {Child_Person_height}})
|
Parameters: {:Child_Person_age=>41, :Child_Person_height=>70}
Ruby: | .create(q: {[:Child, :Person] => {age: 41, height: 70}})
|
Cypher: | CREATE (q:`Child`:`Person` {age: $q_Child_Person_age, height: {q_Child_Person_height}})
|
Parameters: {:q_Child_Person_age=>41, :q_Child_Person_height=>70}
Ruby: | .create([:Child, :Person] => {age: 41, height: 70})
|
Cypher: | CREATE (:`Child`:`Person` {age: $Child_Person_age, height: {Child_Person_height}})
|
Parameters: {:Child_Person_age=>41, :Child_Person_height=>70}
Ruby: | .create_unique('(:Person)')
|
Cypher: |
|
Ruby: | .create_unique(age: 41, height: 70)
|
Cypher: | CREATE UNIQUE ( {age: $age, height: {height}})
|
Parameters: {:age=>41, :height=>70}
Ruby: | .create_unique(Person: {age: 41, height: 70})
|
Cypher: | CREATE UNIQUE (:`Person` {age: $Person_age, height: {Person_height}})
|
Parameters: {:Person_age=>41, :Person_height=>70}
Ruby: | .create_unique(q: {Person: {age: 41, height: 70}})
|
Cypher: | CREATE UNIQUE (q:`Person` {age: $q_Person_age, height: {q_Person_height}})
|
Parameters: {:q_Person_age=>41, :q_Person_height=>70}
Ruby: | .merge(:Person).merge(:Thing)
|
Cypher: | MERGE (:Person) MERGE (:Thing)
|
Ruby: | .merge(age: 41, height: 70)
|
Cypher: | MERGE ( {age: $age, height: {height}})
|
Parameters: {:age=>41, :height=>70}
Ruby: | .merge(Person: {age: 41, height: 70})
|
Cypher: | MERGE (:`Person` {age: $Person_age, height: {Person_height}})
|
Parameters: {:Person_age=>41, :Person_height=>70}
Ruby: | .merge(q: {Person: {age: 41, height: 70}})
|
Cypher: | MERGE (q:`Person` {age: $q_Person_age, height: {q_Person_height}})
|
Parameters: {:q_Person_age=>41, :q_Person_height=>70}
Ruby: | .detach_delete(['n', :o])
|
Cypher: |
|
Ruby: | .set_props('n = {name: "Brian"}')
|
Cypher: |
|
Ruby: | .set_props(n: {name: 'Brian', age: 30})
|
Cypher: |
|
Parameters: {:n_set_props=>{:name=>"Brian", :age=>30}}
Ruby: | .set('n = {name: "Brian"}')
|
Cypher: |
|
Ruby: | .set(n: {name: 'Brian', age: 30})
|
Cypher: | SET n.`name` = $setter_n_name, n.`age` = $setter_n_age
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30}
Ruby: | .set(n: {name: 'Brian', age: 30}, o: {age: 29})
|
Cypher: | SET n.`name` = $setter_n_name, n.`age` = $setter_n_age, o.`age` = $setter_o_age
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30, :setter_o_age=>29}
Ruby: | .set(n: {name: 'Brian', age: 30}).set_props('o.age = 29')
|
Cypher: | SET n.`name` = $setter_n_name, n.`age` = $setter_n_age, o.age = 29
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30}
Ruby: | .on_create_set('n = {name: "Brian"}')
|
Cypher: | ON CREATE SET n = {name: "Brian"}
|
Ruby: | .on_create_set(n: {name: 'Brian', age: 30})
|
Cypher: | ON CREATE SET n.`name` = $setter_n_name, n.`age` = $setter_n_age
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30}
Ruby: | .on_create_set(n: {name: 'Brian', age: 30}, o: {age: 29})
|
Cypher: | ON CREATE SET n.`name` = $setter_n_name, n.`age` = $setter_n_age, o.`age` = $setter_o_age
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30, :setter_o_age=>29}
Ruby: | .on_create_set(n: {name: 'Brian', age: 30}).on_create_set('o.age = 29')
|
Cypher: | ON CREATE SET n.`name` = $setter_n_name, n.`age` = $setter_n_age, o.age = 29
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30}
Ruby: | .on_match_set('n = {name: "Brian"}')
|
Cypher: | ON MATCH SET n = {name: "Brian"}
|
Ruby: | .on_match_set(n: {name: 'Brian', age: 30})
|
Cypher: | ON MATCH SET n.`name` = $setter_n_name, n.`age` = $setter_n_age
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30}
Ruby: | .on_match_set(n: {name: 'Brian', age: 30}, o: {age: 29})
|
Cypher: | ON MATCH SET n.`name` = $setter_n_name, n.`age` = $setter_n_age, o.`age` = $setter_o_age
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30, :setter_o_age=>29}
Ruby: | .on_match_set(n: {name: 'Brian', age: 30}).on_match_set('o.age = 29')
|
Cypher: | ON MATCH SET n.`name` = $setter_n_name, n.`age` = $setter_n_age, o.age = 29
|
Parameters: {:setter_n_name=>"Brian", :setter_n_age=>30}
Ruby: | .remove(n: [:American, "prop"])
|
Cypher: | REMOVE n:`American`, n.prop
|
Ruby: | .remove(n: :American, o: 'prop')
|
Cypher: | REMOVE n:`American`, o.prop
|
Ruby: | .start('r=node:nodes(name = "Brian")')
|
Cypher: | START r=node:nodes(name = "Brian")
|
Ruby: | .start(r: 'node:nodes(name = "Brian")')
|
Cypher: | START r = node:nodes(name = "Brian")
|
Ruby: | .match(q: Person).where('q.age > 30')
|
Cypher: | MATCH (q:`Person`) WHERE (q.age > 30)
|
Ruby: | .where('q.age > 30').match(q: Person)
|
Cypher: | MATCH (q:`Person`) WHERE (q.age > 30)
|
Ruby: | .where('q.age > 30').start('n').match(q: Person)
|
Cypher: | START n MATCH (q:`Person`) WHERE (q.age > 30)
|
Ruby: | .match(q: {age: 30}).set_props(q: {age: 31})
|
Cypher: | MATCH (q {age: {q_age}}) SET q = $q_set_props
|
Parameters: {:q_age=>30, :q_set_props=>{:age=>31}}
Ruby: | .match(q: Person).with('count(q) AS count')
|
Cypher: | MATCH (q:`Person`) WITH count(q) AS count
|
Ruby: | .match(q: Person).with('count(q) AS count').where('count > 2')
|
Cypher: | MATCH (q:`Person`) WITH count(q) AS count WHERE (count > 2)
|
Ruby: | .match(q: Person).with(count: 'count(q)').where('count > 2').with(new_count: 'count + 5')
|
Cypher: | MATCH (q:`Person`) WITH count(q) AS count WHERE (count > 2) WITH count + 5 AS new_count
|
Ruby: | .match(q: Person).match('r:Car').break.match('(p: Person)-->q')
|
Cypher: | MATCH (q:`Person`), r:Car MATCH (p: Person)-->q
|
Ruby: | .match(q: Person).break.match('r:Car').break.match('(p: Person)-->q')
|
Cypher: | MATCH (q:`Person`) MATCH r:Car MATCH (p: Person)-->q
|
Ruby: | .match(q: Person).match('r:Car').break.break.match('(p: Person)-->q')
|
Cypher: | MATCH (q:`Person`), r:Car MATCH (p: Person)-->q
|
Ruby: | .with(:a).order(a: {name: :desc}).where(a: {name: 'Foo'})
|
Cypher: | WITH a ORDER BY a.name DESC WHERE (a.name = $a_name)
|
Parameters: {:a_name=>"Foo"}
Ruby: | .with(:a).limit(2).where(a: {name: 'Foo'})
|
Cypher: | WITH a LIMIT $limit_2 WHERE (a.name = $a_name)
|
Parameters: {:a_name=>"Foo", :limit_2=>2}
Ruby: | .with(:a).order(a: {name: :desc}).limit(2).where(a: {name: 'Foo'})
|
Cypher: | WITH a ORDER BY a.name DESC LIMIT $limit_2 WHERE (a.name = $a_name)
|
Parameters: {:a_name=>"Foo", :limit_2=>2}
Ruby: | .order(a: {name: :desc}).with(:a).where(a: {name: 'Foo'})
|
Cypher: | WITH a ORDER BY a.name DESC WHERE (a.name = $a_name)
|
Parameters: {:a_name=>"Foo"}
Ruby: | .limit(2).with(:a).where(a: {name: 'Foo'})
|
Cypher: | WITH a LIMIT $limit_2 WHERE (a.name = $a_name)
|
Parameters: {:a_name=>"Foo", :limit_2=>2}
Ruby: | .order(a: {name: :desc}).limit(2).with(:a).where(a: {name: 'Foo'})
|
Cypher: | WITH a ORDER BY a.name DESC LIMIT $limit_2 WHERE (a.name = $a_name)
|
Parameters: {:a_name=>"Foo", :limit_2=>2}
Ruby: | .with('1 AS a').where(a: 1).limit(2)
|
Cypher: | WITH 1 AS a WHERE (a = $a) LIMIT $limit_2
|
Parameters: {:a=>1, :limit_2=>2}
Ruby: | .match(q: Person).where('q.age = $age').params(age: 15)
|
Cypher: | MATCH (q:`Person`) WHERE (q.age = $age)
|
Parameters: {:age=>15}