Getting ProcedureNotFound when trying to test apoc.create.virtualPath procedure

Hi Neo4j Community,

I hope this message finds you well. I'm currently working on creation of virtual path like the example below:

</>
MATCH (a)-[r]->(b)
where a.name="Derek Jaun"
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.virtualPath([labelA],{name: aName},rel_type,{since:2009},[labelB],{name: bName}) yield from, rel, to
RETURN *;
</>

I'm receiving this error:

Neo.ClientError.Procedure.ProcedureNotFound

There is no procedure with the name apoc.create.virtualPath registered for this database instance. Please ensure you've spelled the procedure name correctly and that the procedure is properly deployed.

  • neo4j version : Neo4j AuraDb

Thank you in advance for your time and assistance.

Best regards,

It looks like that procedure is not part of the apoc core supported on Aura.

As a work around, you can use the supported functions to manually create two virtual nodes and a virtual relationship between the two virtual nodes.

MATCH (a)-[r]->(b)
where a.name="Derek Jaun"
WITH head(labels(a)) AS labelA, head(labels(b)) AS labelB, type(r) AS rel_type, a.name AS aName, b.name AS bName
WITH apoc.create.vNode([labelA],{name: aName}) as from, apoc.create.vNode([LabelB],{name: bName}) as to, rel_type
RETURN from, to, apoc.create.vRelationship(from, rel_type, {}, to) as rel

Thank you Gary,

Will this workaround result in the creation of duplicate nodes when the same node is involved in multiple relationships?

My goal is to append node with new calculated properties, but without changing the graph and relationship between them.
I hope I'm not taking the wrong path. :sweat_smile:

That is a valid point. My approach was a little naive. The ‘a’ node will be duplicated.

Try this.

MATCH (a)
where a.name="Derek Jaun"
WITH a, apoc.create.vNode([head(labels(a))],{name: a.name}) as from
MATCH (a)-[r]->(b)
WITH from, type(r) as rel_type, apoc.create.vNode([head(labels(b))],{name: b.name}) as to
RETURN from, to, apoc.create.vRelationship(from, rel_type, {}, to) as rel

Hi Gary,
It's functioning as expected with no duplication in the 'a' node. However, preventing duplication in the 'b' node is a more intricate task. Nevertheless, I'll still consider it a viable solution.

Are you getting duplicate virtual nodes for a single ‘b’ node?

this is the graph with real nodes


With your solution, I can partially address all relationships as follows:

And when I attempted to display the missing node using a union script like this:
</>
MATCH (a)
where a.name="Derek Jaun"
WITH a, apoc.create.vNode([head(labels(a))],{name: a.name, color:"clr"}) as from
MATCH (a)-[r]->(b)
WITH from, type(r) as rel_type, apoc.create.vNode([head(labels(b))],{name: b.name, color:"cv"}) as to
RETURN from, to, apoc.create.vRelationship(from, rel_type, {}, to) as rel
union
MATCH (b)
where b.name="Derek Jaun"
WITH b, apoc.create.vNode([head(labels(b))],{name: b.name, color:"clr"}) as to
MATCH (a)-[r]->(b)
WITH to, type(r) as rel_type, apoc.create.vNode([head(labels(a))],{name: a.name, color:"cv"}) as from
RETURN from, to, apoc.create.vRelationship(from, rel_type, {}, to) as rel
</>
the result is

Thank you again

I am assuming Derek Juan is the middle node, which is attached to four nodes. If you expected four "b" nodes, but you only got two, it is because you specified the relationship's direction in the pattern (a)-[r]->(b). You can overcome this by removing the direction constraint. You will then get all four attached nodes.

MATCH (a)
where a.name="Derek Jaun"
WITH a, apoc.create.vNode([head(labels(a))],{name: a.name}) as from
MATCH (a)-[r]-(b)
WITH from, type(r) as rel_type, apoc.create.vNode([head(labels(b))],{name: b.name}) as to
RETURN from, to, apoc.create.vRelationship(from, rel_type, {}, to) as rel

HI Gary

Unfortunately, this solution also generates duplicate nodes 'b'.

I believe it's necessary to establish an additional virtual relationship that describes the opposite direction, from nodes to the central node.

Sorry, I was a little sloppy in my responses. I simulated it this time to get it right. We only need one minor modification to remove the duplicates. We can use the 'distinct' clause to remove the duplicate 'b' nodes before creating the virtual nodes and relationships.

create
(a:Node{name:"A"}),
(b:Node{name:"B"}),
(c:Node{name:"C"}),
(d:Node{name:"D"}),
(e:Node{name:"E"}),
(a)<-[:LIST_WITH]-(b),
(a)<-[:LIST_WITH]-(c),
(a)<-[:LIST_WITH]-(d),
(a)<-[:LIST_WITH]-(e),
(a)-[:LIST_WITH]->(c),
(a)-[:LIST_WITH]->(e),
(d)-[:LIST_WITH]->(c)

Here is the final query:

MATCH (a)
where a.name="Derek Jaun"
WITH a, apoc.create.vNode([head(labels(a))],{name: a.name}) as from
MATCH (a)-[r]-(b)
WITH distinct from, type(r) as rel_type, b
WITH from, rel_type, apoc.create.vNode([head(labels(b))],{name: b.name}) as to
RETURN from, to, apoc.create.vRelationship(from, rel_type, {}, to) as rel

Note: If you want a virtual relationship in both directions, then you should just use the original relationships. The virtual nodes and relationships allow you to visualize the data differently. In this case, you are simplifying the graph to presumably show the important entities.

However, in this manner, all the relationships share the same direction, which is not accurate (from data perspective).
:thinking:?

It you want to represent the direction, then you need all the relationships. At that point, your have everything in the original data.