I would like to spilt this into three things. The first is the Label for the node and the next things (two or more) the nodes Attributes. I am using APOC because I can dynamically set the nodes label (s) where I can't do this in standard Cypher.
What is a good way to do this.. I need to say something like
Split this element into a list, take the first one and make that the node’s label and then the following ones split them again on a “-” and create as many node attributes as I need.
with "LabelTerm1;attribute1Name-Value1;attribute2Name-Value2;attribute3Name-Value3" as input
with split(input,";") as elements
with head(elements) as label, apoc.map.fromPairs([i in tail(elements)|split(i,"-")]) as map
call apoc.create.node([label], map) yield node
return node
I will try this.. but.. it looks like this is exactly what I need.. Dude.. you are the best.. man.. if this works.. you would have saved my AGAIN.. Dude.. Thanks man.. you are wonderful.. I only wish I could do something for you. let me work on this and I will let you know what happens.. thanks man
now I just have to figure out how to Skip elements in the csv file that are blank.. .. :)
will dig into the APOC stuff to see if I can find that out.. You cant mix Cypher
ForEach(_ In Case When (row.Country is not null) Then [1] Else End|
sort of things with Apoc commands.. so.. must be something nice in APOC to do this..
I will draw up an example.. thanks man.. I am use to doing something like
ForEach(_ In Case When (row.Country is not null) Then [1] Else End| do my cypher here..
)
That way i know my Country column for that row is, not null.. So.. in apoc there must be a way to test this.. so I dont do a split on a null and throw an exception.. if you see what I am asking.. well it is 11 at night.. I will put together an example.. see the problem and reason for the question? I found some APOC if then else mechanism that I will explore.. Thanks man for helping me.
I prefer using a call subquery instead of the for each. The similar solution would be:
Call {
with row
With row.Country is not null
//do some cypher
}
The one caveat is that you can’t return anything, as the rest of the query will terminate for the rows that don’t meet the criteria.
apoc does have procedures for executing condition logic. For read-only cypher, there is apoc.case and apoc.when. The equivalent procedures where you can have write operations are apoc.do.case and apoc.do.when
Let me know what example you come with and we can try to solve it.
The first “with” in a call subquery has to be a simple import, meaning just listing the variable to import. A second “with” can be used to filter using a “where” clause.
This should fix it.
load csv with headers from file:///example.csv as exampleRow with exampleRow
Call {
With exampleRow
With exampleRow
Where exampleRow.LevelOne is not null
with split(exampleRow.LevelOne,";") as elements
with head(elements) as label, apoc.map.fromPairs([i in tail(elements)|split(i,"-")]) as map
call apoc.create.node([label], map) yield node
return node
}
When you return something in a subquery it gets appended to the result in the outer query. In your case, when the where clause condition is not met, the subquery will return null and the outer query will terminate. In your case you have nothing following the subquery, so this is not an issue.
Also, you don’t need the subquery for your use case. The following should work as well.
load csv with headers from file:///example.csv as exampleRow
With exampleRow
Where exampleRow.LevelOne is not null
with split(exampleRow.LevelOne,";") as elements
with head(elements) as label, apoc.map.fromPairs([i in tail(elements)|split(i,"-")]) as map
call apoc.create.node([label], map) yield node
return node
One small question.. sorry to bother you again.. First.. this works great! But lets say, instead of creating attributes in the newly created node.. the items after the node label were other nodes (proxy nodes) that i wanted to connect to the first node..
something like this maybe.. ParentNodeLabel(ParntAttrName1-ParntAttrValue1|ParntAttrName2-ParntAttrValue2);ChildNode1Label(AttrName1.1-AttrValue1.1|AttrName1.2-AttrValue1.2);ChildNode2Label(AttrName2.1-AttrValue2.1|AttrName2.2-AttrValue2.2|AttrName3.2-AttrValue3.2)
so ParentNodeLabel would point to ChildNodes 1 and 2, each would have attributes enclosed in something like parentheses.. see sometimes I need the parent node to hold values, and sometimes I need to have that parent node points to proxy nodes that will later be filled in from other data sources, thus their ids, shown here in attribute values. These formats will not be mixed in the same file.. that would be nuts. Nice but.. nuts. Hope this makes some kind of sense..
thanks man.. thanks again.. sigh.. complex projects here..
So, you want to do something similar, but now provide a parent and multiple child nodes in your encoded string? If this is correct, I think I can work it out. Can we change the encoding so it is easier? If you are flexible on it, the following would be easier than enclosing the attribute/value pairs in parenthesis.
with "ParentNodeLabel|ParntAttrName1-ParntAttrValue1|ParntAttrName2-ParntAttrValue2;ChildNode1Label|AttrName1.1-AttrValue1.1|AttrName1.2-AttrValue1.2;ChildNode2Label|AttrName2.1-AttrValue2.1|AttrName2.2-AttrValue2.2|AttrName3.2-AttrValue3.2" as row
with split(row,";") as items
with head(items) as parent, tail(items) as children
with split(parent,"|") as parentItems, [i in children | split(i,"|")] as childItems
with
head(parentItems) as parentLabel,
apoc.map.fromPairs([i in tail(parentItems)|split(i,"-")]) as parentMap,
childItems
call apoc.create.node([parentLabel], parentMap) yield node
with node as parentNode, childItems
unwind childItems as child
with
parentNode,
head(child) as childLabel,
apoc.map.fromPairs([i in tail(child)|split(i,"-")]) as childMap
call apoc.create.node([childLabel], childMap) yield node
create(parentNode)-[r:HAS_CHILD]->(node)
return parentNode, r, node as childNode