简体   繁体   中英

Cypher for neo4j

I was trying to create a union of two optional matches (as shown below) but instead of a union I'm getting an intersection of the two. How should I change this query to get the required union?

optional match (a:PA)-[r2:network*2]-(b:PA) where a.last_name='smith'      
And  Not (a:PA)-[:network]-(b:PA)  
optional match (a:PA)-[r3:network*3]-(b:PA) where a.last_name='smith'
And  Not (a:PA)-[:network]-(b:PA) 
return b.first_name, count(r2), count(r3)

This graph database is supposed to mimic a social network.Through the first optional match I have tried to locate second degree connections in the user's(smith's) network and the count of times they appear as a 2nd degree connection in his network. The second match does the same for the 3rd degree connections.

But the query is returning the intersection of the 2 optional matches instead of their union ie I'm getting a count of only those names which can be mapped as both a 2 degree as well as a 3 degree connection with respect to the user(smith).

Instead I would like to get the name of all the 2nd degree and 3rd degree connections along with the counts. How shall I modify this query to get the required results?

I think in your case the union is not required:

match path = (a:PA {last_name: 'smith'})-[r2:network*2..3]-(b:PA) 
where not (a:PA)-[:network]-(b:PA)
with b.first_name as name,
     CASE WHEN length(path) = 2 THEN 1 ELSE 0 END as deg2
     CASE WHEN length(path) = 3 THEN 1 ELSE 0 END as deg3
RETURN name, sum(deg2), sum(deg3)

I think what you might be after is something like the following query. It does the following:

  1. match smith
  2. optionally match smith's 2nd degree PA
  3. collect the 2nd degree connections
  4. optionally match smith's 3rd degree PA
  5. collect the 3nd degree connections
  6. return the collections of 2nd and 3rd degree PA along with the size of each.

Here is the proposed query

match (a:PA)
where a.last_name='smith'      
with a
optional match (a)-[r2:network*2]-(b:PA) 
where Not (a)-[:network]-(b)  
with a, collect(b.first_name) as 2_deg
optional match (a)-[r3:network*3]-(b:PA) 
where Not (a)-[:network]-(b) 
return 2_deg, collect(b.first_name) as 3_deg, size(2_deg) as num_2_deg, size(3_deg) as num_3_deg

If you did want to actually union the two different queries you need a return statement for each half, matching columns and UNION ALL . Here is a sample but I don't think it is what you are seeking.

optional match (a:PA)-[r2:network*2]-(b:PA) 
where a.last_name='smith'      
And  Not (a:PA)-[:network]-(b:PA)  
return b.first_name, count(r2) as num
UNION ALL
optional match (a:PA)-[r3:network*3]-(b:PA) 
where a.last_name='smith'
And  Not (a:PA)-[:network]-(b:PA) 
return b.first_name, count(r3) as num

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM