问题
Requirements: Find out two or more related matching nodes and display them as groups without repeating all possible combination of matches
Data structure:
E1 is entity 1 N1 is name of entity 1 P1 is phone of entity 1
E2 is entity 2 N2 is name of entity 2 P2 is phone of entity 2
E3 is entity 3 N3 is name of entity 3 P3 is phone of entity 3
Query Used:
start e1=node:entities('entityID:90754 OR entityID:113184 OR entityID:29472')
match (n1)<-[:HAS_NAME]-(e1)-[:HAS_PHONE]-(p1), (p1)-[m:MATCHES_TO]-(p2), (p2)-[:HAS_PHONE]- (e2)-[:HAS_NAME]-(n2), (n1)-[nm:MATCHES_TO]-(n2)
return e1, n1, p1, collect(e2), collect(n2), collect(p2);
Output of the query
# | e1 | n1 | p1 | collect(e2) | collect(n2) | collect(p2)
Row1 | entity1 | name of entity1 | phone of entity1 | phone of entity2, phone of entity3 | name of entity2, name of entity3 | phone of entity2, phone of entity3
Row2 | entity2 | name of entity2 | phone of entity2 | phone of entity1 | name of entity1 | phone of entity1
Row3 | entity3 | name of entity3 | phone of entity3 | phone of entity1 | name of entity1 | phone of entity1
Issues: Only the first row of the result set is sufficient. Row 2 and Row 3 are not essential since they are already part of the collection of the first row.
Someone please help how I can build a cypher query so that I get only row in the above example
回答1:
You can first order the result by the head entity name(e1.name), and filter out any related entity(e2) whose name is less than the head entity name(e1.name) because such e2 must appear as a head element of a row X before the current row and e1 must appear as a related entity in that row X, in other words, the pair (e2, e1) already appears in a previous row.
You then only need to exclude the rows that has no related entities left as shown in the query below,
Match (p1:EntityPhone)<-[:HasPhone]-(e1:Entity)-[:HasName]->(n1:EntityName), (p2:EntityPhone)<-[:HasPhone]-(e2:Entity)-[:HasName]->(n2:EntityName), (n1)-[:Matches]-(n2), (p1)-[:Matches]-(p2)
With e1.name as ename, filter(x in collect(e2.name): x > e1.name) as e2names
Order by ename
With ename, e2names, reduce(e2count = 0 , n in e2names : e2count + 1) as e2count
Where e2count > 0
Return ename, e2names
Here is the web console for this query, http://console.neo4j.org/?id=ljfbpb
来源:https://stackoverflow.com/questions/18504778/neo4j-cypher-find-out-two-or-more-related-matching-nodes-and-display-them-as-gr