-
Notifications
You must be signed in to change notification settings - Fork 494
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
Add apoc.diff user function #760
Conversation
Hi Benjamin, thanks a lot for your contribution.
Thanks |
Sorry fogot the CLA: https://neo4j.com/developer/cla/ |
Hi Michael, thanks for your feedback! Short question on point 3: Do you think we should add both, a procedure that returns detailed diff information and a function that only returns a boolean or just the function? Thanks |
Yes both would be good. the equality would be the same as We could also add sub.functions that provide the difference, intersection, disjunctions of maps Michael |
Hi Michael, I signed the CLA and reworked all the code. We now have different functions that return only boolean values and one procedure that returns all the detailed information (examples described in the adoc file). The tests are using the embedded Neo4j now and the guava dependency is not needed anymore. 👍 Maybe I can add more functionality in an additional PR if this one will be merged. Hope you like it! 😉 |
@jexp I just rebased to the last commit with the Travis fix - it's all green now! 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please have a look at my comments
src/main/java/apoc/diff/Diff.java
Outdated
public GraphDatabaseService db; | ||
|
||
@UserFunction | ||
@Description("apoc.diff.maps([leftMap],[rightMap])" ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add an explanation to all descriptions ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not really a diff, it's just an equals, which is the same as WHERE leftMap = rightMap
in cypher, or?
I thought you'd have a function that outputs the differences between both, which then should go to apoc.map.*
src/main/java/apoc/diff/Diff.java
Outdated
|
||
@UserFunction | ||
@Description("apoc.diff.properties([leftNodeId],[rightNodeId])") | ||
public boolean properties(@Name("leftNodeId") Long leftNodeId, @Name("rightNodeId") Long rightNodeId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
support nodes and not node-ids, if someone has node-ids they can use cypher to look them up.
as you want to use this from cypher you most often have nodes, and not node ids.
@@ -0,0 +1,110 @@ | |||
package apoc.diff; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps rather call it apoc.equals.*
a diff is more detailed difference computation and output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw. Java equality is not the same as Cypher equality
e.g. in Cypher all these are equal (int)1 == long)1 == (byte)1 == (float)1.0 == (double)1.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reworked
src/main/java/apoc/diff/Diff.java
Outdated
|
||
@Procedure(mode = Mode.READ) | ||
@Description("apoc.diff.nodes([leftNodeId],[rightNodeId])") | ||
public Stream<DiffResult> nodes(@Name("leftNodeId") Long leftNodeId, @Name("rightNodeId") Long rightNodeId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could have this both as function and procedure, the function then would return a map with the fields of the DiffResult being keys.
src/main/java/apoc/diff/Diff.java
Outdated
private Map<String, Object> getPropertiesLeftOnly(Node leftNode, Node rightNode) { | ||
Map<String, Object> leftOnly = new HashMap<>(); | ||
leftOnly.putAll(leftNode.getAllProperties()); | ||
leftOnly.putAll(rightNode.getAllProperties()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't need it
also you should access the node's properties only once per node, it's an expensive operation
so all these private methods should take Maps instead.
src/main/java/apoc/diff/Diff.java
Outdated
keyPairs.putAll(leftNode.getAllProperties()); | ||
keyPairs.keySet().retainAll(rightNode.getAllProperties().keySet()); | ||
|
||
Iterator it = keyPairs.entrySet().iterator(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use foreach
src/main/java/apoc/diff/Diff.java
Outdated
Iterator it = keyPairs.entrySet().iterator(); | ||
while (it.hasNext()) { | ||
Map.Entry entry = (Map.Entry)it.next(); | ||
if (!leftNode.getAllProperties().get(entry.getKey()).equals(rightNode.getAllProperties().get(entry.getKey()))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you already have it in keyPairs
src/main/java/apoc/diff/Diff.java
Outdated
while (it.hasNext()) { | ||
Map.Entry entry = (Map.Entry)it.next(); | ||
if (!leftNode.getAllProperties().get(entry.getKey()).equals(rightNode.getAllProperties().get(entry.getKey()))) { | ||
Map<String, Object> pairs = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably eaiser to use a 2 element array or list
src/main/java/apoc/diff/Diff.java
Outdated
Map<String, Object> pairs = new HashMap<>(); | ||
pairs.put("leftValue", leftNode.getAllProperties().get(entry.getKey())); | ||
pairs.put("rightValue", rightNode.getAllProperties().get(entry.getKey())); | ||
differing.put(entry.getKey().toString(), pairs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keys are always strings
src/main/java/apoc/diff/Diff.java
Outdated
|
||
Iterator it = keyPairs.entrySet().iterator(); | ||
while (it.hasNext()) { | ||
Map.Entry entry = (Map.Entry)it.next(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing generics, they come with foreach
@binarycoded ping :) |
@jexp I'm still here! :) Will have a look at your comments asap. |
ping again :) |
I'd really love to merge this in :) Please have a look at my feedback. Thank you!! |
Hey @jexp, I hope I find some time in the next few days ... |
Hi @jexp |
Looks great, thanks so much. |
The new procedure
apoc.diff.nodes
returns an overview of all node property differences of two nodes given by their nodeIds. The new functionality is documented in a new*.adoc
-file (with usage and example Cypher) and covered by a unit test.