от Neo4j к GraphJSON с Ruby

Я пытаюсь получить визуализацию с помощью d3.js или alchemy.js, но, в частности, алхимия требует, чтобы источник данных был в GraphJSON.

Я играл с учебными пособиями и примерами Макса Де Марци (используя неографию), Майкла Хангера (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

Я возьму таблицу путей. Но он не отформатирован так, как мне нужно, и я понятия не имею, как он может перейти из этого формата в формат 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"
    ]
  ]
}

person stephen    schedule 08.02.2016    source источник


Ответы (2)


Я думаю, что одна проблема, с которой вы столкнулись, заключается в том, что вместо двух узлов и одного отношения вы сопоставляете три узла и два отношения. Вот ваш 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

Также обратите внимание, что если вы не укажете никаких меток, ваш запрос может быть медленным, в зависимости от количества узлов). Зависит от того, что вам нужно ;)

person Brian Underwood    schedule 09.02.2016

Этот запрос Cypher должен возвращать массив ребер в соответствии с форматом примера:

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"
          }
]
person William Lyon    schedule 09.02.2016