Reputation: 77
I have a database like in this question:
Neo4j - Finding the Shortest Path between two nodes based on relationship property
CREATE (some_point_1:Point {title:'Some Point 1'})
CREATE (some_point_2:Point {title:'Some Point 2'})
CREATE (some_point_3:Point {title:'Some Point 3'})
CREATE (some_point_4:Point {title:'Some Point 4'})
CREATE (some_point_5:Point {title:'Some Point 5'})
CREATE (some_point_6:Point {title:'Some Point 6'})
CREATE (some_point_1)-[:distance {value:100}]->(some_point_2)
CREATE (some_point_2)-[:distance {value:150}]->(some_point_4)
CREATE (some_point_1)-[:distance {value:200}]->(some_point_3)
CREATE (some_point_3)-[:distance {value:300}]->(some_point_4)
CREATE (some_point_2)-[:distance {value:500}]->(some_point_5)
CREATE (some_point_4)-[:distance {value:300}]->(some_point_5)
CREATE (some_point_5)-[:distance {value:300}]->(some_point_6)
CREATE (some_point_6)-[:distance {value:300}]->(some_point_1)
Now I'm trying to execute a query like this: (from a Rails app)
MATCH (start:Point {title: 'Some Point 1'}), (end:Point {title: 'Some Point 5'})
MATCH p=(start)-[:distance*]->(end)
WITH p,reduce(s = 0, r IN rels(p) | s + r.value) AS dist
RETURN p, dist ORDER BY dist DESC
I'm trying to do a similar query with the active model wrapper, but it's not working :(
Is there a way to execute a pure Cypher query from neo4jrb or neo4j-core?
Upvotes: 1
Views: 337
Reputation: 10856
Guillermo is absolutely right, but I thought I would give a stab at some code:
Point.where(title: 'Some Point 1').connected(:end, :rels, rel_length: :any).where(title: 'Some Point 5')
.query.with(:p, dist: 'reduce(s = 0, r IN :rels | s + r.value)')
.return(:p, :dist)
.order(disc: :desc)
That will give you an Enumerable
which you can iterate over or call to_a
on. Or you could return a two dimensional array directly:
.order(disc: :desc)
.pluck(:p, :dist)
This assumes an ActiveNode
model as Guillermo said. Something like;
class Point
include Neo4j::ActiveNode
property :title
has_many :out, :connected, type: :distance, model_class: :Point
end
The name of the association may or may not be what you want, I just guessed.
Upvotes: 0
Reputation: 10856
MATCH (start:Point {title: 'Some Point 1'}), (end:Point {title: 'Some Point 5'}) MATCH p=(start)-[:distance*]->(end) WITH p,reduce(s = 0, r IN rels(p) | s + r.value) AS dist RETURN p, dist ORDER BY dist DESC
Guillermo is absolutely right, but I thought I would give a stab at some code:
Point.where(title: 'Some Point 1').connected(:end, :rels, rel_length: :any).where(title: 'Some Point 5')
.query.with(:p, dist: 'reduce(s = 0, r IN :rels | s + r.value)')
.return(:p, :dist)
.order(disc: :desc)
That will give you an Enumerable
which you can iterate over or call to_a
on. Or you could return a two dimensional array directly:
.order(disc: :desc)
.pluck(:p, :dist)
This assumes an ActiveNode
model as Guillermo said. Something like;
class Point
include Neo4j::ActiveNode
property :title
has_many :out, :connected, type: :distance, model_class: :Point
end
The name of the association may or may not be what you want, I just guessed.
Upvotes: 0
Reputation: 755
Yes, you can easily do Cypher directly if you want via the neo4j-core
gem (which you need anyways when using the neo4j
gem).
For example: n = Neo4j::Session.query("MATCH (n) RETURN n").first
(assuming you have configured you application to communicate with the Neo4j server).
If you are using the neo4j
gem you need to have the corresponding ActiveNode
(and possibly ActiveRel
) models in your application so that you can do your queries. This gem is pretty much a nice wrapper of the standard ActiveModel
for Neo4j :)
You have more information on how to: https://github.com/neo4jrb/neo4j-core/wiki/Queries
You can also move from a QueryProxy
chain to a Neo4j::Core::Query
. See https://github.com/neo4jrb/neo4j/wiki/Search-and-Match#detailed-querying
Upvotes: 1