== Virtual Nodes/Rels

Virtual Nodes and Relationships don't exist in the graph, they are only returned to the UI/user for representing a graph projection.
They can be visualized or processed otherwise.
Please note that they have negative id's.

[cols="1m,5"]
|===
| CALL apoc.create.vNode(['Label'], {key:value,...}) YIELD node | returns a virtual node
| apoc.create.vNode(['Label'], {key:value,...}) | returns a virtual node
| CALL apoc.create.vNodes(['Label'], [{key:value,...}]) | returns virtual nodes
| CALL apoc.create.vRelationship(nodeFrom,'KNOWS',{key:value,...}, nodeTo) YIELD rel | returns a virtual relationship
| apoc.create.vRelationship(nodeFrom,'KNOWS',{key:value,...}, nodeTo) | returns a virtual relationship
| CALL apoc.create.vPattern({_labels:['LabelA'],key:value},'KNOWS',{key:value,...}, {_labels:['LabelB'],key:value}) | returns a virtual pattern
| CALL apoc.create.vPatternFull(['LabelA'],{key:value},'KNOWS',{key:value,...},['LabelB'],{key:value}) | returns a virtual pattern
|===

// * TODO `CALL apoc.create.vGraph([nodes, {_labels:[],... prop:value,...}], [rels,{_from:keyValueFrom,_to:{_label:,_key:,_value:value}, _type:'KNOWS', prop:value,...}],['pk1','Label2:pk2'])

=== Virtual Nodes/Rels Example

.Virtual node and virtual relationship `vNode`, `vRelationship`

From a simple dataset

[source,cypher]
----
CREATE(a:Person)-[r:ACTED_IN]->(b:Movie)
----

We can create a virtual copy, adding as attribute `name` the labels value

[source,cypher]
----
MATCH (a)-[r]->(b)
WITH head(labels(a)) AS l, head(labels(b)) AS l2, type(r) AS rel_type, count(*) as count
CALL apoc.create.vNode([l],{name:l}) yield node as a
CALL apoc.create.vNode([l2],{name:l2}) yield node as b
CALL apoc.create.vRelationship(a,rel_type,{count:count},b) yield rel
RETURN *;
----

image::{img}/apoc.create.vRelationshipAndvNode.png[width=800]

Virtual nodes and virtual relationships have always a negative id

image::{img}/vNodeId.png[width=200]

.Virtual pattern `vPattern`

[source,cypher]
----
CALL apoc.create.vPattern({_labels:['Person'],name:'Mary'},'KNOWS',{since:2012},{_labels:['Person'],name:'Michael'})
----

image::{img}/apoc.create.vPattern.png[width=800]

We can add more labels, just adding them on `_labels`

[source,cypher]
----
CALL apoc.create.vPattern({_labels:['Person', 'Woman'],name:'Mary'},'KNOWS',{since:2012},{_labels:['Person', 'Man'],name:'Michael'})
----

image::{img}/apoc.create.vPatternLabels.png[width=800]

.Virtual pattern full `vPatternFull`

[source,cypher]
----
CALL apoc.create.vPatternFull(['British','Person'],{name:'James', age:28},'KNOWS',{since:2009},['Swedish','Person'],{name:'Daniel', age:30})
----

image::{img}/apoc.create.vPatternFull.png[width=800]

We can create a virtual pattern from an existing one

[source,cypher]
----
CREATE(a:Person {name:'Daniel'})-[r:KNOWS]->(b:Person {name:'John'})
----

From this dataset we can create a virtual pattern

[source,cypher]
----
MATCH (a)-[r]->(b)
WITH head(labels(a)) AS labelA, head(labels(b)) AS labelB, type(r) AS rel_type, a.name AS aName, b.name AS bName
CALL apoc.create.vPatternFull([labelA],{name: aName},rel_type,{since:2009},[labelB],{name: bName}) yield from, rel, to
RETURN *;
----

image::{img}/apoc.create.vPatternFullTwo.png[width=800]