Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apoc.merge.node just for Match-only #2674

Closed
zirkelc opened this issue Mar 31, 2022 · 0 comments
Closed

apoc.merge.node just for Match-only #2674

zirkelc opened this issue Mar 31, 2022 · 0 comments

Comments

@zirkelc
Copy link
Contributor

zirkelc commented Mar 31, 2022

Feature description (Mandatory)

apoc.merge.node
apoc.merge.relationship

apoc.merge.node allows to dynamically MERGE a node with labels and properties that can be provided as parameters instead of building a static Cyper query beforehand. This is useful in cases where we unwind on multiple rows and the MERGE clause would be different for each row:

UNWIND $rows AS row
CALL apoc.merge.node(row.labels, row.match, row.onCreateProps, row.onMatchProps) YIELD node
RETURN collect(id(node)) as nodeIds

In the same way, we can use apoc.merge.relationship to dynamically MERGE a relationship with type and properties provided as parameters. However, we must also provide the start and end node of the relationship. Both nodes can be matched with apoc.merge.node without providing properties to be merge (last two params):

UNWIND $rows AS row
CALL apoc.merge.node(row.start.labels, row.start.match) YIELD node as startNode
CALL apoc.merge.node(row.end.labels, row.end.match) YIELD node as endNode
CALL apoc.merge.relationship(startNode, row.relType, row.match, row.onCreateProps, endNode, row.onMatchProps) YIELD rel
RETURN collect(id(rel)) as relationshipIds

In the second example, I'm using apoc.merge.node to MATCH the start and end nodes without actually creating or changing them. My assumption is though, that Neo4j still write-locks these nodes which affects the performance and would hinder optimisations such as parallelisation via apoc.periodic.iterate due to deadlocks on the same node.

I would like to suggest a new procedure apoc.match.node or apoc.nodes.match to dynamically MATCH nodes. The implementation would be fairly easy as we could copy apoc.merge.node and change the Cypher query in line 77 from MERGE to MATCH:

private Result getNodeResult(List<String> labelNames, Map<String, Object> identProps, Map<String, Object> props, Map<String, Object> onMatchProps) {
if (identProps ==null || identProps.isEmpty()) {
throw new IllegalArgumentException("you need to supply at least one identifying property for a merge");
}
String labels = labelString(labelNames);
Map<String, Object> params = Util.map("identProps", identProps, "onCreateProps", props, "onMatchProps", onMatchProps);
String identPropsString = buildIdentPropsString(identProps);
final String cypher = "MERGE (n:" + labels + "{" + identPropsString + "}) ON CREATE SET n += $onCreateProps ON MATCH SET n += $onMatchProps RETURN n";
return tx.execute(cypher, params);
}

Considered alternatives

The default values of apoc.merge.node for onCreateProps and onMatchProps is {}. This means no change to the properties on CREATE or MATCH. Therefore, we could alternatively add condition in Java to check if properties have been provided. If not, we could switch the Cypher query from MERGE to MATCH in this case.


If you find this request useful and would be wiling to add it to APOC, then I would go ahead and submit a PR for this! Let me know what you think! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants