1
votes

I want to create multiple neo4j nodes and relationships in one Cypher transaction. I'm using py2neo which allows issuing multiple Cypher statements in one transaction .

I thought I'd add a statement for each node and relationship I create:

tx.append('CREATE (n:Label { prop: val })')
tx.append('CREATE (m:Label { prop: val2 })')

Now I want to create a relationship between the two created nodes:

tx.append('CREATE (n)-[:REL]->(m)')

This doesn't work as expected. No relationship is created between the first two nodes, since there's no n or m in the context of the last statement (there is a new relationship between two new nodes - four nodes are created in total)

Is there a way around this? Or should I combine all the calls to CREATE (around 100,000 per logical transaction) in one statement?

It just hurts my brain thinking about such a statement, because I'll need to store everything on one big StringIO, and I lose the ability to use Cypher query parameters - I'll need to serialize dictionaries to text myself.

UPDATE: The actual graph layout is more complicated than that. I have multiple relationship types, and each node is connected to at least two other nodes, while some nodes are connected to hundreds of nodes.

2
It won't fail, it will just create two nodes with no labels or properties. The relationship will still be created.Nicole White
OK, yes, this doesn't work as expected...zmbq
That's because identifiers are only relevant within the scope of the query: stackoverflow.com/a/34074151/2848578Nicole White
Yes, I know that, I was hoping there was some way around this without creating one huge query.zmbq
If you are doing a large data import consider using LOAD CSV. See stackoverflow.com/questions/34118491/… for an example. Also see stackoverflow.com/questions/34124759/batch-loading-neo4j/… for an example using py2neo WriteBatchWilliam Lyon

2 Answers

1
votes

You don't need multiple queries. You can use a single CREATE to create each relationship and its related nodes:

tx.append('CREATE (:Label { prop: val })-[:REL]->(:Label { prop: val2 })')
0
votes

Do something like this:

rels = [(1,2), (3,4), (5,6)]

query = """
CREATE (n:Label {prop: {val1} }),
       (m:Label {prop: {val2} }),
       (n)-[:REL]->(m)
"""

tx = graph.cypher.begin()

for val1, val2 in rels:
    tx.append(query, val1=val1, val2=val2)

tx.commit()

And if your data is large enough consider doing this in batches of 5000 or so.