I have written test code to connect to neo4j server from java app and execute two cypher queries in ONE Transaction.I did not find detailed example for executing two queries and retrieving result in neo4j Documentation
Though the code works, my question is:
Are these the best practices to use neo4j(AsyncSession, Transaction) and java(CompletionStage/ CompletableFuture) interface?
Are the queries executed Asynchronously if I use CompletableFuture.get() at the end?
Disclaimer: I am not super familiar with these Java APIs
I noticed a few things.
The most important one, in my opinion, is that you could rewrite everything into a single Cypher query with UNWIND $product_ids AS id MERGE (p:Product {id: id }) RETURN p.id and retrieve each row, instead of composing several queries' result, that would probably simplify the code quite a bit. Note that the initial ON CREATE clause is not needed, because MERGE already CREATEs everything defined in the pattern if the pattern is not MATCHed in the graph (in that case, the id attribute is part of the pattern so it will be created if absent).
Then, a few technical details that I noticed:
Before calling java.util.concurrent.CompletableFuture#allOf, you should convert every CompletionStage to CompletableFuture with java.util.concurrent.CompletionStage#toCompletableFuture (it might be a no-op today, but that's not guaranteed in the future). Indeed, the toArray call is otherwise unsafe.
I also wonder if the code could not be simplified if you call join on the allOf result, surrounding the call with a try-catch:
Using join has simplified the code a lot and I have updated the implementation to convert CompletionStage to CompletableFuture now.
Also, our actual queries are quite different, I used those queries just to test (Apologies, if it was not clear earlier). Sharing few actual queries:
MATCH (entity:Entity { id: 'Default/CAMR-Finance25/Account/c5abf4a2-aecf-4bb4-a830-98a2af92cd91'}) WITH entity
MERGE (alert:Alert { id: 'Default/CAMR-Finance25/Account/c5abf4a2-aecf-4bb4-a830-98a2af92cd91' ,taskId: 1161 ,alertType: 'IdentityStatusValidation' ,entityGlobalId: 'c5abf4a2-aecf-4bb4-a830-98a2af92cd91' })
ON CREATE SET
alert.id = 'Default/CAMR-Finance25/Account/c5abf4a2-aecf-4bb4-a830-98a2af92cd91' ,alert.taskId= 1161 ,alert.alertType= 'IdentityStatusValidation' ,alert.entityGlobalId= 'c5abf4a2-aecf-4bb4-a830-98a2af92cd91' ,alert.raisedTime= 1610010155452 ,alert.summary= 'IdentityStatusValidation has failed, Please check task messages for more details.' ,alert.messages= '[{"message":"User ( [MMISHRA] ) could not be found. A valid and active User ID must be provided.","severity":"WARNING"}]'
ON MATCH SET
alert.id = 'Default/CAMR-Finance25/Account/c5abf4a2-aecf-4bb4-a830-98a2af92cd91' ,alert.taskId= 1161 ,alert.alertType= 'IdentityStatusValidation' ,alert.entityGlobalId= 'c5abf4a2-aecf-4bb4-a830-98a2af92cd91' ,alert.updateTime= 1610340489245 ,alert.summary= 'IdentityStatusValidation has failed, Please check task messages for more details.' ,alert.messages= '[{"message":"User ( [MMISHRA] ) could not be found. A valid and active User ID must be provided.","severity":"WARNING"}]'
MERGE (entity)-[r:WITH_ALERT]->(alert)
Nice, it's good to know you could simplify the code
My initial remark about MERGE and ON CREATE/ON MATCH still applies: you should not include attributes in these clauses that are already part of the MERGE pattern (i.e. remove id, taskId, alertType and entityGlobalId from the ON xxx SET clauses).
Moreover, if you need to set properties in both ON CREATE/ON MATCH cases, you can simply write MERGE... SET (without ON CREATE/ON MATCH), it will set the properties all the time (which could be useful for the messages and summary).
In short, your example query would become:
MATCH (entity:Entity { id: 'Default/CAMR-Finance25/Account/c5abf4a2-aecf-4bb4-a830-98a2af92cd91'})
MERGE (alert:Alert {
id: 'Default/CAMR-Finance25/Account/c5abf4a2-aecf-4bb4-a830-98a2af92cd91',
taskId: 1161,
alertType: 'IdentityStatusValidation',
entityGlobalId: 'c5abf4a2-aecf-4bb4-a830-98a2af92cd91'
})
ON CREATE SET alert.raisedTime = 1610010155452
ON MATCH SET alert.updateTime = 1610340489245
SET alert.summary= 'IdentityStatusValidation has failed, Please check task messages for more details.' ,
alert.messages= '[{"message":"User ( [MMISHRA] ) could not be found. A valid and active User ID must be provided.","severity":"WARNING"}]'
MERGE (entity)-[r:WITH_ALERT]->(alert)