neo4j-contrib / neovis.js

Neo4j + vis.js = neovis.js. Graph visualizations in the browser with data from Neo4j.
Apache License 2.0
1.59k stars 324 forks source link

When returning the result from the apoc.path.subgraphAll from the server to the function updateWithFunction, the visualization is not updating #351

Open kunalj1994 opened 1 year ago

kunalj1994 commented 1 year ago

Expected Behavior (Mandatory)

The visualization should update with the nodes and relationships from the response.

Actual Behavior (Mandatory)

Nothing happens, but the same query when executed with updateWithCypher function updates the visualization and shows the right nodes and relationships.

How to Reproduce the Problem

By using this query -

MATCH (p) where ID(p) = ${nodeId}
      CALL apoc.path.subgraphAll(p, {
          minLevel: 0,
          maxLevel: 1
      })
      YIELD nodes, relationships
      RETURN nodes, relationships

and capturing the result in a variable and passing it to updateWithFunction.

Simple Example

const config: NeovisConfig = {
  visConfig: {
    height: '100%',
    width: '100%',
    interaction: {
      hover: true,
      hoverConnectedEdges: true,
      selectConnectedEdges: false,
      multiselect: true,
      zoomView: true,
    },
    physics: {
      barnesHut: {
        gravitationalConstant: -50000,
        avoidOverlap: 0.4,
      },
    },
    nodes: {
      shape: 'circle',
      widthConstraint: 80,
    },
    edges: {
      hoverWidth: 2,
      selectionWidth: 0,
      smooth: {
        enabled: true,
        type: 'continuous',
        roundness: 0.15,
      },
      arrows: {
        to: {
          enabled: true,
          type: 'arrow',
          scaleFactor: 0.5,
        },
      },
    },
  },
  groupAsLabel: true,

  initialCypher: 'MATCH (n) RETURN n',
}
Node id can come from the clicked event mentioned below.
const result =  <result of this query - MATCH (p) where ID(p) = ${nodeId}
      CALL apoc.path.subgraphAll(p, {
          minLevel: 0,
          maxLevel: 1
      })
      YIELD nodes, relationships
      RETURN nodes, relationships
}>

vis.registerOnEvent(NeoVisEvents.ClickNodeEvent, e => {
  vis.updateWithFunction(() => result)
})

Specifications (Mandatory)

Currently used versions

Versions

kunalj1994 commented 1 year ago

I have went through the code thoroughly and pinpointed two instances in the code where I think the bug could lie, When running the createSingleRecord function, since the input is a JSON it doesnt recognize it as a instance of Record, so it executes the corresponding if statement which then executes this line

record = new Neo4j.types.Record(
        record.keys,
        fields.map(dumbToNeo4j),
        (record as any)._fieldLookup,
      )

This dumbToNeo4j function looks to me as the culprit, because when running a regular query, the structure looks like this -

[
    {
      keys: ['n', 'r'],
      length: 2,
      _fields: [
       {},{}
      ],
      _fieldLookup: {
        n: 0,
        r: 1,
      },
    },
    ]

But when running the apoc.path.subgraph query, the resulting structure looks like this -

[{
  "keys": ["nodes", "relationships"],
  "length": 2,
  "_fields": [
    [{}, {}],
    [{}, {}]
  ],
  "_fieldLookup": {
    "nodes": 0,
    "relationships": 1
  }
}]

So this dumbToNeo4j is unable to account for _fields being a nested array and returns this result - {"keys":["nodes","relationships"],"length":2,"_fields":[null,null],"_fieldLookup":{"nodes":0,"relationships":1}}

thebestnom commented 1 year ago

It should account for fields in array, but maybe I forgot, Ill try to fix that, fun to have to do deseriallization myself as neo4j didn't wrote a seriallizinzation function

kunalj1994 commented 1 year ago

Perfect, thank you for your swift reply and looking into it.