cancel
Showing results for 
Search instead for 
Did you mean: 

Why don't add a CALL <cypherFileName.cyp> {} instruction?

paolodipietro58
Graph Voyager

I'm using quite extensively the CALL {} subquery instruction.

I believe that an extension, to allow calling a reusable subquery should be extremely useful:

I'm thinking to something like the following:

CALL 'filename.cyp' WITH x1 AS y1, ..., xn AS yn {
   WITH y1, ..., yn
}

Feedback will be appreciated.

Paolo

4 REPLIES 4

giuseppe_villan
Graph Fellow

@paolodipietro58

At least personally, it's not fully clear what do you have in mind,
How should the file 'filename.cyp' be?


Maybe with the APOC, in particular this apoc.cypher.runFile - APOC Documentation
you could create your repetitive queries.

It is just like a function!
Imagine to have the following query fragment:

CALL {
    WITH item1, item2
    WITH item1, item2
        WHERE item2 IS NOT NULL

    MERGE (item1)-[h:VERB]->(item2)
}

CALL {
    WITH item1, item2
    WITH item1, item2
        WHERE item2 IS NULL
    
    MERGE (error:Error)
    MERGE (item1)-[h:ERROR_MSG]->(error)
}

The fragment could be saved in a file, named 'fragment.cyp` then I'd call the fragment as:

CALL 'fragment.cyp' WITH order AS item1, item AS item2, :HAS AS :VERB, :HAS_NO_ITEM as :ERROR_MSG

and

CALL 'fragment.cyp' WITH organisation AS item1, store AS item2, :HAS AS :VERB, :HAS_NO_ORGANIZATION as :ERROR_MSG

Maybe I should achieve the same result with the apoc.cypher.runfile you just cited, but please, can you transform my example in a query running with the apoc, and show me how should I pass the actual parameters?

Regarding MERGE (item1)-[h:VERB]->(item2) and MERGE (item1)-[h:ERROR_MSG]->(error),
afaik the type relationship cannot be parameterized.

You can use the equivalent apoc.merge.relationship but in this case you cannot use a subquery structure like your because of WHERE item2 IS NOT NULL which, unlike MERGE, block the query in the first subquery if item2 is not null.

However with this structure you can use the apoc.do.case(condition, firstQuery, secondQuery, {}) procedure, where firstQuery will be executed when item2 IS NOT NULL, otherwise the secondQuery.


So you can create this file filename.cypher:

CALL apoc.do.when($item2 IS NOT NULL, 
	"CALL apoc.merge.relationship(item1, type1, {}, {}, item2) YIELD rel RETURN 1", 
	"MERGE (error:Error) WITH error, item1, item2, type2 CALL apoc.merge.relationship(item1, type2, {}, {}, error) YIELD rel RETURN 1",
	{item1: $item1, item2: $item2, type1: $type1, type2: $type2});

and then execute:

match (organization:Organization)
with organization, null as store // this is an example to be changed
 // pass your query....
// ... here is the code
call apoc.cypher.runFile("filename.cypher", 
    {parameters: {item1: organization, item2: store, type1: "HAS", type2: "HAS_NO_ORGANIZATION"}})
// in parameters I pass the parameters  $item1, $item2, $type1 and $type2 present in filename.cypher
yield result, row
return result, row

@giuseppe.villani Thank you Giuseppi. Your solution surely runs, but it looks supercomplicate the problem.

if it is not possible parametrize the relationships, the game is not worth the candle!

Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

On November 16 and 17 for 24 hours across all timezones, you’ll learn about best practices for beginners and experts alike.