Extracting subgraph into JSON format

I want to extract subgraph into json format..

subgraph

I tried using following query:

match path = (n)-[r]-(b) WHERE (n.user_id='0000001') with collect(path) as paths
call apoc.convert.toTree(paths) yield value
return value

But it doesn't give me correct json representing the attached graph.

Perhaps you can tell us what kind of JSON output you want? This subgraph you've shown us has no implicit hierarchy. You're going to have to show what kind of structure you want before we can help.

following is the JSON output, i am looking for:

{
"nodes": [
{
"label": "User",
"key": "0000001",
"property1":"",
"property2":""
},
{
"label": "Tweet",
"key": "967824267948773376",
"property1": "",
"property2": ""
}
],
"relationships": [
{
"type": "FOLLOWS",
"from_node": {
"label": "User",
"key": "user_id"
},
"to_node": {
"label": "User",
"key": "user_id"
}
},
{
"type": "POSTS",
"from_node": {
"label": "User",
"key": "0000001"
},
"to_node": {
"label": "Tweet",
"key": "967824267948773376"
}
}
]
}

I suggest you to use apoc.path.subgraphAll
it will give you all the subgraph for some node to its max depth.

Okay, so you want JSON output of a list of nodes (all properties + label, assuming only a single label per node in your model), and a list of relationships (all properties + type, + start and end nodes but only the label and key for each node.

This query should do the trick.

MATCH (n) 
WHERE n.user_id='0000001'
CALL apoc.path.subgraphAll(n, {maxLevel:1}) YIELD nodes, relationships
WITH [node in nodes | node {.*, label:labels(node)[0]}] as nodes, 
     [rel in relationships | rel {.*, fromNode:{label:labels(startNode(rel))[0], key:startNode(rel).key}, toNode:{label:labels(endNode(rel))[0], key:endNode(rel).key}}] as rels
WITH {nodes:nodes, relationships:rels} as json
RETURN apoc.convert.toJson(json)

Keep in mind you really should be using labels in your query, corresponding with the index you SHOULD have on the label + user_id property for fast lookup of your start node.

Next we use apoc.path.subgraphAll(), as this will yield lists of distinct nodes and distinct relationships. You can adjust maxLevel to whatever depth you want (or leave off for unlimited depth). You didn't specify a type or direction for your match, but if you have restrictions here you can add them with a relationshipFilter config parameter in the procedure call.

Since nodes don't output their labels when returning them, and same with types for relationships, we need to project out the desired properties first (including start and end nodes for relationships), stuff those into a map, then convert it to JSON.

2 Likes

The query you mentioned in above reply finds subgraph correctly if we have one unique node (n). But if I have a list of nodes, I am not getting correct subgraph:
for example:
MATCH (n)
WHERE n.user_id='0000001 OR n.user_id='0000002'
CALL apoc.path.subgraphAll(n, {maxLevel:1}) YIELD nodes, relationships
WITH [node in nodes | node {., label:labels(node)[0]}] as nodes,
[rel in relationships | rel {.
, fromNode:{label:labels(startNode(rel))[0], key:startNode(rel).key}, toNode:{label:labels(endNode(rel))[0], key:endNode(rel).key}}] as rels
WITH {nodes:nodes, relationships:rels} as json
RETURN apoc.convert.toJson(json)

I am expecting subgraph for both the nodes id='0000001' and '0000002' but I am getting subgraph only for id='0000001'

can you please advise?

You need to group by your start node.

(please also format your code snippets)

MATCH (n:User)
WHERE  n.user_id IN ['0000001, '0000002']
CALL apoc.path.subgraphAll(n, {maxLevel:1}) YIELD nodes, relationships
WITH n, 
          [node in nodes | node {.*, label:labels(node)[0]}] as nodes,
          [rel in relationships | rel {.*, type: type(rel),
           fromNode:{label:labels(startNode(rel))[0], key:startNode(rel).key}, 
           toNode:  {label:labels(endNode(rel))[0], key:endNode(rel).key}}] as rels
RETURN apoc.convert.toJson({nodes:nodes, relationships:rels})
1 Like