We are running neo4j version 3.3.
we have 2 types of nodes (total of 10k nodes) which have a total of 650k relationships. We heap size of the memory is 8GB.
The Nodes have a UNIQUE CONSTRAINT on the node ID.
We are using the official neo4j-python official driver (we also tried to use the py2neo driver but the performance was even worse).
While running the following query, the performance is VERY problematic. For a 1 hop distance it takes a few minutes (even for a list of several nodes). For a 2 hop distance (like the query below) with a list of 1 node it takes over 40 mintues.
Any ideas how to improve the performance?
query = '''MATCH (n1:label1)
WHERE n1.ID IN {list}
MATCH paths=((n1)-[:relType*..2]->(n2))
WHERE n1.ID <> n2.ID AND (n2:label1 OR n2:label2)
RETURN DISTINCT paths
UNION
MATCH (n1:label2)
WHERE n1.ID IN {list}
MATCH paths=((n1)-[:relType*..2]->(n2))
WHERE n1.ID <> n2.ID AND (n2:label1 OR n2:label2)
RETURN DISTINCT paths'''
with driver.session() as session:
results = list(session.run(query, parameters={'list':list_nodes}))
if results:
df = neo4j_graph_to_df(results)
The function to process the result is below:
def neo4j_graph_to_df(paths):
paths_dict=OrderedDict()
print(paths)
for (pathID, e) in enumerate(paths):
paths_dict[pathID]=OrderedDict()
nodes_list = [n for n in e['paths'].nodes]
rels_list = [r for r in e['paths'].relationships]
pathl = [x for x in itertools.chain.from_iterable(itertools.zip_longest(nodes_list, rels_list)) if x ]
for i, p in enumerate(pathl):
if isinstance(p, neo4j.v1.types.Node):
paths_dict[pathID]['Node'+str(i)+'Label']= str(next(iter(p.labels)))
dicti = dict(zip(['Node'+str(i)+str(np) for np in p.properties.keys()], p.properties.values()))
paths_dict[pathID] = OrderedDict( {**paths_dict[pathID], **dicti} )
if isinstance(p, neo4j.v1.types.Relationship):
paths_dict[pathID]['Rel'+str(i-1)]=p.type
dicti = dict(zip(['Rel'+str(i)+str(rp) for rp in p.properties.keys()], p.properties.values()))
paths_dict[pathID] =OrderedDict( {**paths_dict[pathID], **dicti } )
df = pd.DataFrame.from_dict(paths_dict, orient='index').fillna('0')
df = df.drop_duplicates().reset_index()
return df