使用 Ruby 从 Neo4j 到 GraphJSON
from Neo4j to GraphJSON with Ruby
我正在尝试使用 d3.js 或 alchemy.js 进行可视化——但是 Alchemy 特别需要数据源在 GraphJSON 中。
我一直在研究 Max De Marzi(使用 neography)、Michael Hunger(cy2neo、js)、Neo4j 和 Neo4j.rb 的教程和示例——但我似乎无法全部掌握那里的路。主要是因为我不知道自己在做什么——但这就是我努力学习的方式。
我想要实现的目标是:
https://bl.ocks.org/mbostock/3750558
或此处的默认可视化:http://graphalchemist.github.io/Alchemy/#/docs
您还可以在此页面上找到 GraphJSON 格式,以了解它应该是什么样子:http://graphalchemist.github.io/Alchemy/#/docs
如果我运行以下...
get '/followers' do
Neo4j::Session.open(:server_db, "http://localhost:7474")
query = Neo4j::Session.query('MATCH (a--(b)--(c) RETURN a,b,c LIMIT 30')
puts "--------------"
puts query_to_graph_json(query)
query_to_graph_json(query)
end
# This is supposed to grab nodes and edges, but it never gets edges.
# It's originally from a conversation at the neo4j.rb site
def query_to_graph_json(query)
nodes = {}
edges = {}
add_datum = Proc.new do |datum|
case datum
when Neo4j::ActiveNode, Neo4j::Server::CypherNode
nodes[datum.neo_id] = {
id: datum.neo_id,
properties: datum.props #was attributes, but kept saying that wasn't a method
}
when Neo4j::ActiveRel, Neo4j::Server::CypherRelationship
edges[[datum.start_node.neo_id, datum.end_node.neo_id]] = {
source: datum.start_node.neo_id,
target: datum.end_node.neo_id,
type: datum.rel_type,
properties: datum.props
}
else
raise "Invalid value found: #{datum.inspect}"
end
end
query.each do |row|
row.to_a.each do |datum|
if datum.is_a?(Array)
datum.each {|d| add_datum.call(d) }
else
add_datum.call(datum)
end
end
end
{
nodes: nodes.values,
edges: edges.values
}.to_json
end
我会得到...
{
"nodes": [
{
"id": 597,
"properties": {
"name": "John",
"type": "Person"
}
},
{
"id": 127,
"properties": {
"name": "Chris",
"type": "Person"
}
},
{
"id": 129,
"properties": {
"name": "Suzie",
"type": "Person"
}
},
],
"edges": [
]
}
问题是我需要边缘。
如果我运行...
get '/followers' do
content_type :json
neo = Neography::Rest.new("http://localhost:7474")
cypher = "MATCH (a)--(b)--(c) RETURN ID(a),a.name,ID(b),b.name,ID(c),c.name LIMIT 30"
puts neo.execute_query(cypher).to_json
end
我会得到 table 条路径。但它没有按照我需要的方式格式化——我不知道它如何从这种格式转换为 GraphJSON 格式。
{
"columns": [
"ID(a)",
"a.name",
"ID(b)",
"b.name",
"ID(c)",
"c.name"
],
"data": [
[
597,
"John",
127,
"Chris",
129,
"Suzie"
],
[
597,
"John",
6,
"Adam",
595,
"Pee-Wee"
]
]
}
这个 Cypher 查询应该 return 边缘数组按照示例格式:
MATCH (a)-[r]-(b)
WITH collect(
{
source: id(a),
target: id(b),
caption: type(r)
}
) AS edges
RETURN edges
运行 针对一些示例数据,结果如下所示:
[
{
"source": 9456,
"target": 9454,
"caption": "LIKES"
},
{
"source": 9456,
"target": 9454,
"caption": "LIKES"
},
{
"source": 9456,
"target": 9455,
"caption": "LIKES"
},
{
"source": 9454,
"target": 9456,
"caption": "LIKES"
}
]
我认为您遇到的一个问题是,您匹配的不是两个节点和一个关系,而是三个节点和两个关系。这是你的 MATCH
:
MATCH (a)--(b)--(c)
应该是这样的:
MATCH (a)-[b]-(c)
在 MATCH
子句中 []
可以被排除,你可以只做一个原始的 --
(或 -->
或 <--
)代表关系。
尽管如此,您可能想查询一个特定的方向。如果您双向查询,您将获得两次相同的关系,并交换开始和结束节点。
使用 neo4j-core
(作为维护者之一,我偏向于它;)
nodes = []
rels = []
session.query('(source)-[rel]->(target)').pluck(:source, :rel, :target).each do |source, rel, target|
nodes << source
nodes << target
rels << rel
end
{
nodes: nodes,
edges: rels
}.to_json
另请注意,如果您不指定任何标签,您的查询可能会很慢,具体取决于节点数)。取决于你需要什么 ;)
我正在尝试使用 d3.js 或 alchemy.js 进行可视化——但是 Alchemy 特别需要数据源在 GraphJSON 中。
我一直在研究 Max De Marzi(使用 neography)、Michael Hunger(cy2neo、js)、Neo4j 和 Neo4j.rb 的教程和示例——但我似乎无法全部掌握那里的路。主要是因为我不知道自己在做什么——但这就是我努力学习的方式。
我想要实现的目标是: https://bl.ocks.org/mbostock/3750558 或此处的默认可视化:http://graphalchemist.github.io/Alchemy/#/docs
您还可以在此页面上找到 GraphJSON 格式,以了解它应该是什么样子:http://graphalchemist.github.io/Alchemy/#/docs
如果我运行以下...
get '/followers' do
Neo4j::Session.open(:server_db, "http://localhost:7474")
query = Neo4j::Session.query('MATCH (a--(b)--(c) RETURN a,b,c LIMIT 30')
puts "--------------"
puts query_to_graph_json(query)
query_to_graph_json(query)
end
# This is supposed to grab nodes and edges, but it never gets edges.
# It's originally from a conversation at the neo4j.rb site
def query_to_graph_json(query)
nodes = {}
edges = {}
add_datum = Proc.new do |datum|
case datum
when Neo4j::ActiveNode, Neo4j::Server::CypherNode
nodes[datum.neo_id] = {
id: datum.neo_id,
properties: datum.props #was attributes, but kept saying that wasn't a method
}
when Neo4j::ActiveRel, Neo4j::Server::CypherRelationship
edges[[datum.start_node.neo_id, datum.end_node.neo_id]] = {
source: datum.start_node.neo_id,
target: datum.end_node.neo_id,
type: datum.rel_type,
properties: datum.props
}
else
raise "Invalid value found: #{datum.inspect}"
end
end
query.each do |row|
row.to_a.each do |datum|
if datum.is_a?(Array)
datum.each {|d| add_datum.call(d) }
else
add_datum.call(datum)
end
end
end
{
nodes: nodes.values,
edges: edges.values
}.to_json
end
我会得到...
{
"nodes": [
{
"id": 597,
"properties": {
"name": "John",
"type": "Person"
}
},
{
"id": 127,
"properties": {
"name": "Chris",
"type": "Person"
}
},
{
"id": 129,
"properties": {
"name": "Suzie",
"type": "Person"
}
},
],
"edges": [
]
}
问题是我需要边缘。
如果我运行...
get '/followers' do
content_type :json
neo = Neography::Rest.new("http://localhost:7474")
cypher = "MATCH (a)--(b)--(c) RETURN ID(a),a.name,ID(b),b.name,ID(c),c.name LIMIT 30"
puts neo.execute_query(cypher).to_json
end
我会得到 table 条路径。但它没有按照我需要的方式格式化——我不知道它如何从这种格式转换为 GraphJSON 格式。
{
"columns": [
"ID(a)",
"a.name",
"ID(b)",
"b.name",
"ID(c)",
"c.name"
],
"data": [
[
597,
"John",
127,
"Chris",
129,
"Suzie"
],
[
597,
"John",
6,
"Adam",
595,
"Pee-Wee"
]
]
}
这个 Cypher 查询应该 return 边缘数组按照示例格式:
MATCH (a)-[r]-(b)
WITH collect(
{
source: id(a),
target: id(b),
caption: type(r)
}
) AS edges
RETURN edges
运行 针对一些示例数据,结果如下所示:
[
{
"source": 9456,
"target": 9454,
"caption": "LIKES"
},
{
"source": 9456,
"target": 9454,
"caption": "LIKES"
},
{
"source": 9456,
"target": 9455,
"caption": "LIKES"
},
{
"source": 9454,
"target": 9456,
"caption": "LIKES"
}
]
我认为您遇到的一个问题是,您匹配的不是两个节点和一个关系,而是三个节点和两个关系。这是你的 MATCH
:
MATCH (a)--(b)--(c)
应该是这样的:
MATCH (a)-[b]-(c)
在 MATCH
子句中 []
可以被排除,你可以只做一个原始的 --
(或 -->
或 <--
)代表关系。
尽管如此,您可能想查询一个特定的方向。如果您双向查询,您将获得两次相同的关系,并交换开始和结束节点。
使用 neo4j-core
(作为维护者之一,我偏向于它;)
nodes = []
rels = []
session.query('(source)-[rel]->(target)').pluck(:source, :rel, :target).each do |source, rel, target|
nodes << source
nodes << target
rels << rel
end
{
nodes: nodes,
edges: rels
}.to_json
另请注意,如果您不指定任何标签,您的查询可能会很慢,具体取决于节点数)。取决于你需要什么 ;)