cancel
Showing results for 
Search instead for 
Did you mean: 

Virtual nodes and properties

guido
Node Clone

I want only a limited number of node properties to show in a graph, in a specific, non-alphabetical order. I was advised that this is not possible in standard graphs and that I needed to create virtual nodes.
So I wrote this code:

MATCH (p:Producer)-[r:HAS_NAME_VARIANT]->(n:Name)
WHERE n.text = $neodash_name_text
WITH r, apoc.create.vNode(['Name'],{language:n.Language, name:n.text, remarks:n.comment}) as to, apoc.create.vNode(['Producer'],{type:p.Type, entity:n.entity}) as from
RETURN from, to, apoc.create.vRelationship(from, 'Variant',{Qualif:r.qualification},to) AS rel;

(where $neodash_name_text is a search term)

The graph is created, but I have 3 questions:
1. only 1 n is shown, but I want all n-nodes to show. Am I using the wrong apoc? I tried apoc.create.vNodes and apoc.graph.fromData (as in the Manual) but they return a blank screen;
2. the node properties still appear in alphabetical order (capitals first), how can I determine the order myself?
3. is there a way to leave properties out in those node descriptions where they are null or empty? E.g. the property n.comment is only occasionally filled. Only in those cases the line <remarks:n.comment> should appear.

Thanks for your help!

1 ACCEPTED SOLUTION

You can add other values to exclude in the second array.  Try this:

match (p:Producer)-[r:HAS_NAME_VARIANT]->(n:Name)
with apoc.map.clean({type: p.Type, entity: n.entity}, [], [""]) as pMap, 
apoc.map.clean({language: n.Language, name: n.text, remarks: n.comment}, [], [""]) as nMap,
apoc.map.clean({Qualif: r.qualification}, [], [""]) as rMap
with rMap, apoc.create.vNode(['Name'], nMap) as to, apoc.create.vNode(['Producer'], pMap) as from
return from, to, apoc.create.vRelationship(from, 'Variant', rMap, to) AS rel

I believe the issue with the property ordering is due to the fact that the data structure holding the values is a java map. Since it is returning them in alphabetical order, it must be a TreeMap implementation of a Map that is being used. I don't see a way around this. At least it is ordered, unlike if a hash map was used. 

View solution in original post

6 REPLIES 6

There is apoc.create.virtual.fromNode which allows to leave off properties.

https://neo4j.com/labs/apoc/4.0/overview/apoc.create/apoc.create.virtual.fromNode/

also you need to first create your virtual nodes put them into a map (apoc.map.fromNodes(nodesList, 'key') and then fetch them from by key there for your relationships. I have a code example for that I think in the video

https://neo4j.com/videos/bettter-visualization-with-virtual-nodes-and-rels-in-apoc-11/

Nice video.  thanks for explaining virtual nodes/relationships.  Now I understand and see lots of potential uses for them. 

glilienfield
Ninja
Ninja
  1. What issue are you having in item #1?  I created some test data and used your query and I got virtual nodes and relationships for all Producer and Names. 
  2. I don't think there is a way
  3. You could use apoc.map.clean to remove nulls and other unwanted values.  Try this:
match (p:Producer)-[r:HAS_NAME_VARIANT]->(n:Name)
with r, apoc.map.clean({type: p.Type, entity: n.entity}, [], []) as pMap, 
apoc.map.clean({language: n.Language, name: n.text, remarks: n.comment}, [], []) as nMap,
apoc.map.clean({Qualif: r.qualification}, [], []) as rMap
with rMap, apoc.create.vNode(['Name'], nMap) as to, apoc.create.vNode(['Producer'], pMap) as from
return from, to, apoc.create.vRelationship(from, 'Variant', rMap, to) AS rel

Hi @glilienfield,
thanks (again) for your suggestions.

I have solved issue no. 1.

Issue no.2 remains a pain in the rear parts. IMHO (coming from 30 years of front-office relational database projects) the rigidity of properties (labels cannot be changed except in virtual nodes, no other ordering than the standard alphabetical ordering is possible -can something be done about this, please,  @michael_hunger ?) is in sharp contrast with the unparallelled flexibility of the rest of the system...

Issue no.3: I've adopted your solution: it works perfectly for null values (thanks!) but not when the properties are empty. And, as per our previous discussion (about Data Importer and null values), Data Importer only imports empty properties, apoc.map.clean has no effect. I can delete all "" values with a query, but when I use Data Importer for the next batch of data, it reinstalls the empty fields.

You can add other values to exclude in the second array.  Try this:

match (p:Producer)-[r:HAS_NAME_VARIANT]->(n:Name)
with apoc.map.clean({type: p.Type, entity: n.entity}, [], [""]) as pMap, 
apoc.map.clean({language: n.Language, name: n.text, remarks: n.comment}, [], [""]) as nMap,
apoc.map.clean({Qualif: r.qualification}, [], [""]) as rMap
with rMap, apoc.create.vNode(['Name'], nMap) as to, apoc.create.vNode(['Producer'], pMap) as from
return from, to, apoc.create.vRelationship(from, 'Variant', rMap, to) AS rel

I believe the issue with the property ordering is due to the fact that the data structure holding the values is a java map. Since it is returning them in alphabetical order, it must be a TreeMap implementation of a Map that is being used. I don't see a way around this. At least it is ordered, unlike if a hash map was used. 

@glilienfield : brilliant, issue 3 solved!