cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Multiple Nodes creation issue

myrights99
Graph Buddy

Hello:
I am using MERGE to create Node along with property (net) as below in the image. The problem is that one node is created with all the property values rather than creating multiple nodes. I am passing "net" as my dataframe column in MERGE for properties, but only one node is created. Not sure what I am missing?

myrights99_0-1674184663761.png

 

1 ACCEPTED SOLUTION

I realized one more thing. If you merge all the nodes together with one merge statement, than a new path is made between each node if one or more relationships is missing. This is because a merge operation is all or nothing. As such, I decomposed the merging of the path into individual merges between each pair of nodes.  I also added the conversion to numbers in this version.

load csv with headers from "file:///IndiaTowerDump_Data_2000_Records.csv" as row

merge(geo:Geospat{lat: toFloat(row.lat), lon: toFloat(row.lon)})
merge(cid:Cid{cellID: toInteger(row.cell)})
merge(geo)<-[:HAS_LATLON]-(cid)

merge(lac:LAC {area: toInteger(row.area), createdatetimein_Unix: toInteger(row.created), updateddatetimein_Unix: toInteger(row.updated)})
merge(cid)-[:IS_RELATED]->(lac)

merge(mnc:Mnc{net: toInteger(row.net)})
merge(lac)-[:HAS_MNC]->(mnc)

merge(mcc:Mcc{code: toInteger(row.mcc)})
merge(mnc)-[:IS_ASSOCIATED]->(mcc)

 Ignore the earlier graph as well.

View solution in original post

17 REPLIES 17

can you post your query and data you are importing?

def create_mnc_node(tx, pNet):
return tx.run(
"MERGE (n:Mnc {net: $pNet})",
pNet=pNet
)

session = driver.session(database="tower")

# Execute the `create_mnc_node` "unit of work" within a write transaction
session.execute_write(create_mnc_node, pNet=pNet)

This is the query that I want to make it work. but having same issues of single node as mentioned above. So i trying to create multiple nodes for one labels at a time to see if that works?

def create_multi_node(tx, pLat,pLon,pCell,pArea,pNet,pMcc,pCreated,pUpdated):
return tx.run(
"MERGE (:Geospat{lat: $pLat, lon: $pLon})<-[:HAS_LATLON]-(:Cid{cellID: $pCell})-[:IS_RELATED]-> \
(:LAC {area: $pArea, createdatetimein_Unix: $pCreated, updateddatetimein_Unix:$pUpdated })- \
[:HAS_MNC]->(n:Mnc{net: $pNet})-[:IS_ASSOCIATED]->(:Mcc{code: $pMcc})",
pLat=pLat,pLon=pLon,pCell=pCell,pArea=pArea,pNet=pNet,pMcc=pMcc,pCreated=pCreated,pUpdated=pUpdated
)

session = driver.session(database="tower")

# Execute the `create_mnc_node` "unit of work" within a write transaction
session.execute_write(create_multi_node, pLat=pLat,pLon=pLon,pCell=pCell,pArea=pArea,pNet=pNet,pMcc=pMcc,pCreated=pCreated,pUpdated=pUpdated)

Can you provide same data for one call to create_multi_node method? 

Is pNet sent as a list? If so, and you want a new Mnc node for each element of pNet, then the following will achieve that:

 

forEach(p in $pNet | 
    MERGE (n:Mnc {net: p})
)

 

Thanks for your reply, but it's not working; throwing an error. (Error - ClientError: {code: Neo.ClientError.Statement.ParameterMissing} {message: Expected parameter(s): pCell})

def create_multi_node(tx, pCell):
return tx.run(
"forEach(p in $pCell | \
MERGE (c:Cid {cellID: p}) \
)"
)

session = driver.session(database="tower")

# Execute the `create_mnc_node` "unit of work" within a write transaction
session.execute_write(create_multi_node, pCell=pCell)

You did not pass pCell to the 'run' method.

def create_multi_node(tx, pCell):
return tx.run(
"forEach(p in $pCell | \
MERGE (c:Cid {cellID: p}) \
), pCell = pCell"
)

 

I appreciate your help; finally, it is working. Is there a better way to create required multinodes based on labels, or do you recommend creating individual label (multinodes) and then creating relationships?

Thank you again for your help.

If you all the data, it may be easier to add the nodes and relationships at the same time.  What is your circumstance? 

They are all dataframes

pLat = df1['lat']
pLon = df1['lon']
pCell = df1['cell']
pArea = df1['area']
pNet = df1['net']
pMcc = df1['mcc']
pCreated = df1['created']
pUpdated = df1['updated']

What about the larger query? Do you need to fix that too?

I have data for all the nodes, as shown below. If you can help me how to fix that, it will be great.

def create_multi_node(tx, pLat,pLon,pCell,pArea,pNet,pMcc,pCreated,pUpdated):
return tx.run(
"MERGE (:Geospat{lat: $pLat, lon: $pLon})<-[:HAS_LATLON]-(:Cid{cellID: $pCell})-[:IS_RELATED]-> \
(:LAC {area: $pArea, createdatetimein_Unix: $pCreated, updateddatetimein_Unix:$pUpdated })- \
[:HAS_MNC]->(n:Mnc{net: $pNet})-[:IS_ASSOCIATED]->(:Mcc{code: $pMcc})",
pLat=pLat,pLon=pLon,pCell=pCell,pArea=pArea,pNet=pNet,pMcc=pMcc,pCreated=pCreated,pUpdated=pUpdated
)

I am not sure this is what you want. I followed your query, but changed it to work from what I gathered you wanted.

load csv with headers from "file:///IndiaTowerDump_Data_2000_Records.csv" as row
merge(geo:Geospat{lat: row.lat, lon: row.lon})
merge(cid:Cid{cellID: row.cell})
merge(lac:LAC {area: row.area, createdatetimein_Unix: row.created, updateddatetimein_Unix: row.updated })
merge(mnc:Mnc{net: row.net})
merge(mcc:Mcc{code: row.mcc})
merge (geo)<-[:HAS_LATLON]-(cid)-[:IS_RELATED]->(lac)-[:HAS_MNC]->(mnc)-[:IS_ASSOCIATED]->(mcc)

Graph resulting from your data:

Screen Shot 2023-01-21 at 2.45.47 PM.png

I just realized the script imports all the values as a 'string'.  This is the default behavior. You may want numerical values for most of these, since they look like numbers in the spreadsheet. You need to wrap each row property in toInteger() or toFloat() to convert them during the import. 

I realized one more thing. If you merge all the nodes together with one merge statement, than a new path is made between each node if one or more relationships is missing. This is because a merge operation is all or nothing. As such, I decomposed the merging of the path into individual merges between each pair of nodes.  I also added the conversion to numbers in this version.

load csv with headers from "file:///IndiaTowerDump_Data_2000_Records.csv" as row

merge(geo:Geospat{lat: toFloat(row.lat), lon: toFloat(row.lon)})
merge(cid:Cid{cellID: toInteger(row.cell)})
merge(geo)<-[:HAS_LATLON]-(cid)

merge(lac:LAC {area: toInteger(row.area), createdatetimein_Unix: toInteger(row.created), updateddatetimein_Unix: toInteger(row.updated)})
merge(cid)-[:IS_RELATED]->(lac)

merge(mnc:Mnc{net: toInteger(row.net)})
merge(lac)-[:HAS_MNC]->(mnc)

merge(mcc:Mcc{code: toInteger(row.mcc)})
merge(mnc)-[:IS_ASSOCIATED]->(mcc)

 Ignore the earlier graph as well.

Thank you for your excellent help. When I do print (df.dtypes) in my jupyter notebook. below is the output. So I am trying to understand how you are getting it as a 'String'.??

radio object
mcc int64
net int64
area int64
cell int64
unit int64
lon float64
lat float64
range int64
samples int64
changeable int64
created int64
updated int64
averageSignal int64
ID int64

I added the conversion in the last query version.