Accenture/Cymple

Multiple where clause with literal and other implementation difficulties

Closed this issue · 2 comments

I am currently trying to convert a very long cypher command which is highly optimized. However, I stumbled across some difficulties where I do not know if it is possible to implement the exact command using the build in clauses or if I need to make additional custom clauses myself (which I would really like to avoid)

  1. Where clauses that have multiple different conditions:
    Example: MATCH (n:Person) WHERE n.age=32 AND Not n:Teacher

  2. Calls with subqueries (https://neo4j.com/docs/cypher-manual/current/clauses/call-subquery/)
    Example (from cypher docs):
    UNWIND [0, 1, 2] AS x CALL { RETURN 'hello' AS innerReturn } RETURN innerReturn

  3. Condition is Null
    Example: WHERE p.lock is Null OR ...

  4. Union

  5. With x as y without RETURN:
    Example: MATCH (n) WHERE n.age=32 WITH n as n_test WITH [n_test] as n_list RETURN n_list as n_test

  6. Datetime/Duration and apoc calls:
    Example: WHERE x.age=32 OR datetime()<datetime(x.time)+duration.inSeconds(30)
    Example: Call apoc.do.when(condition, UNWIND t as test set test.abc=5 ...)

Hi @Varsius,
Thank you for letting us know of these issues.

Two quick tips:
First, whenever you would like to find out how to write something new, you could first take a look at test_clauses.py, where we added use cases that we though to be common - written both in Cypher and using Cymple.
Second, if you cannot find what you're looking for and it seems like Cymple is missing support for some Cypher syntax, you could always use the cypher() method, that accepts arbitrary string and appends it to your query.

As for your specific points:

  1. Use where_literal(): MATCH (n:Person) WHERE n.age=32 AND Not n:Teacher can be built using match().node('Person', ref_name='n').where_literal('n.age=32 AND NOT n:Teacher')
  2. This is currently unsupported, we will add it sometime soon. For now, you can use cypher().
  3. To build something like MATCH (p) WHERE p.lock IS NULL OR p.value IS NULL, you can use match().node(ref_name='p').where_multiple({'p.lock': 'NULL', 'p.value': 'NULL'}, 'IS', ' OR ', escape=False). For more complex filtering. use where_literal().
  4. UNION is not yet supported :) If you're interested, I encourage you to help and contribute to Cymple by implementing this clause!
  5. To build MATCH (n) WITH n as n_test WITH [n_test] as n_list RETURN n_list as n_test, use match().node(ref_name='n').with_('n as n_test').with_('[n_test] as n_list').return_mapping(('n_list', 'n_test')).
  6. To call a procedure, use call()

Thanks a lot!