cancel
Showing results for 
Search instead for 
Did you mean: 

Match data against a predefined structure

surf_dgm
Node

Hi All

I'm sorry, I'm junior on graph


Here is the issue :

Let's suppose the graph of normal person is figure1
John is describe as picture 2

Is it possible with Neo4J, to match a graph ( John) against another graph the defined a normal person (picture 1) and identify the gap?

Thanks for your help

1 ACCEPTED SOLUTION

I created your scenario:

Try this:

MATCH (a:Person)-[*..]->()
WHERE a.name = "P"
CALL apoc.path.spanningTree(a, {maxLevel: 2}) YIELD path
with nodes(path) as a1
unwind a1 as a2
with collect(distinct labels(a2)) as lbl1

MATCH (b:Person)-[*..]->()
WHERE b.name = "John"
CALL apoc.path.spanningTree(b, {maxLevel: 2}) YIELD path
with lbl1, nodes(path) as b1
unwind b1 as b2
with lbl1, collect(distinct labels(b2)) as lbl2
with apoc.coll.subtract(lbl1, lbl2) AS diff
return diff

Result: ["Belly"]

View solution in original post

11 REPLIES 11

Joel
Ninja
Ninja

there are two helper functions in APOC, that may be worth looking at, I don't think either are a drop in solution for this, but could be useful in building a solution

surf_dgm
Node

Thanks @Joel for your response.

Do you think pattern can help on the issue?
My understanding is that pattern can help design a structure of the database. I'm not sure if my understanding is correct or not.

Joel
Ninja
Ninja

I'm not sure what you mean, but the most obvious (but quite possibly not the best) way to compare is to programmatically walk the "normal" person graph, and an "individual" person graph in parallel, taking note of what's missing in the individual's graph. Starting at the Person node and probably I'd use a breadth first walk. e.g.

Normal has a person node, individual does as well, check same
Normal has child nodes of head, trunk and limbs, this individual (john) does as well, check same
Normal has face and skull child nodes for head, individual does as well, check same
Normal has belly and chest child nodes under trunk, individual has only chest, check John is missing belly node
Normal has feet and hand child nodes under limbs, individual does as well, check same

total result: John is missing the node belly at person->trunk->, maybe return it as person->trunk->belly not sure what you want as output though.

Two notes

  • I believe you are comparing graph structure (e.g. node labels and relationship types), and not comparing two individuals to see if they are the same person (e.g. names must match, etc)
  • This example is trivial, for implementation one would have to handle entire parts of the tree missing (and decide how to handle if there are new/different graph parts, for an individual that aren't in the normal person graph?)

Yes, I'm comparing the structure, not the values

I took a simply example to explain the problem. The graph I'm working on has around 1000 nodes

Thanks for your help @Joel
I think it might be difficult to do this in a graph with 1000 nodes.

Does anyone knows how schema or patterns works?

omerule
Graph Buddy

Goodevening,
Maybe you can use the power of the relations within Neo4j.
A don 't know exactly how to built.

But do something like compare the relations between person and John.
You could make the relations of person as a reference by naming them. And then at creation of John use the same names of person relations. Then get the relations used in person and compare them with the relations used in John.

Yours kindly,
Omer

Hello @omerule
Thanks for your answer

I'm not very sure, I got your point.
I'm trying to check whether two different graphs have the same structure

Not sure here. but if we think the structure is created by the relations (The belly of John could be there but is not attached then the relationship is important. ).
If possible you could make the relationship of person as a convention something like "node2node". Then use that methode in the relations used with John. And then get the relations form person (reference structure?) And compare those relations with the ones used in John.

Thanks @omerule
I understook it when I saw the illustration made by @ameyasoft

I created your scenario:

Try this:

MATCH (a:Person)-[*..]->()
WHERE a.name = "P"
CALL apoc.path.spanningTree(a, {maxLevel: 2}) YIELD path
with nodes(path) as a1
unwind a1 as a2
with collect(distinct labels(a2)) as lbl1

MATCH (b:Person)-[*..]->()
WHERE b.name = "John"
CALL apoc.path.spanningTree(b, {maxLevel: 2}) YIELD path
with lbl1, nodes(path) as b1
unwind b1 as b2
with lbl1, collect(distinct labels(b2)) as lbl2
with apoc.coll.subtract(lbl1, lbl2) AS diff
return diff

Result: ["Belly"]

Thanks @ameyasoft for your help

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.