Filter out relationships based on other relationships properties

Hello all.
I have a graph with nodes representing Hosts, Switches, Zones and Storages in a network.

For an example, suppose this script:

MATCH (wh:Switch)<-[]-(h:Host)-[]->(z:Zone)<-[]-(s:Storage)-[]->(ws:Switch) //Host-Zone-Storage-Switch
WHERE id(h)=0 //Host especΓ­fico
and id(s)=118 //Storage especΓ­fico
return h,z,s,wh,ws;

It will return a graph like this:
graph

What I need is to only show the relationships between nodes 0 and 127, and between 0 and 132 that have the same numbers as the relationship between 0 and 320, which are WWN numbers. The red node is a host, the green nodes are switches and the blue node is a zoning configuration. A host has multiple connections to a number of switches, but I only want to see the ones that are also configured to be in use, which are the ones configured between the host and the zoning.

I already tried the answer given in this answer, and it did not work.

Thanks!

Neo4j version 4.2.1, desktop version 1.3.11

If I understand you correctly....[EDIT] This is wrong! (the bug/feature of the Neo4J Browser is that it shows you all the relationships between nodes that match). See dominicvivek06 post below.

If you use Neo4J Bloom, you can specify which relationships you want and those will be shown and the other relationships that don't match won't show. So, the query you have, only the nodes will appear but the relationships won't. In Bloom, you need to match the relationships too. E.g.

MATCH (wh:Switch)<-[r1]-(h:Host)-[r2]->(z:Zone)<-[r3]-(s:Storage)-[r4]->(ws:Switch)
WHERE id(h)=0 //Host especΓ­fico
and id(s)=118 //Storage especΓ­fico
and r1 ....  // Some conditions on the relationship properties.
return h,z,s,wh,ws,r1, r2, r3, r4;

I found Bloom to be a bit trickier to use than the Browser though.

Hi @wolf_goe,

Welcome to Neo4j Community.

Your question makes me recollect my days of configuring CISCO Catalyst 6000. :slight_smile:

Can you please, run the below cypher and post the output.

CALL apoc.meta.schema() YIELD value as schemaMap
UNWIND keys(schemaMap) as label
WITH label, schemaMap[label] as data
WHERE data.type = "node"
UNWIND keys(data.properties) as property
WITH label, property, data.properties[property] as propData
RETURN label,
property,
propData.type as type,
propData.indexed as isIndexed,
propData.unique as uniqueConstraint,
propData.existence as existenceConstraint

My initial query,

MATCH (h:Host)-[h2z]->(z:Zone)
where id(h)=0
with h2z.WWN as ref_no,h,z,h2z
MATCH (h)-[h2s]->(s:Switch)
where id(s)=118 AND h2s.WWN = ref_no 
return h as Host,z as Zone,s as Switch, h2z,h2s;

not sure, WWN is a label or a property ... the metadata output will provide more details of the schema, after you share the output

Hi Dominic!

The output is:
"label" β”‚"property"β”‚"type" β”‚"isIndexed"β”‚"uniqueConstraint"β”‚"existenceConstraint"β”‚
β•žβ•β•β•β•β•β•β•β•β•β•ͺ══════════β•ͺ════════β•ͺ═══════════β•ͺ══════════════════β•ͺ═════════════════════║
β”‚"Storage"β”‚"name" β”‚"STRING"β”‚false β”‚false β”‚false β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚"Switch" β”‚"name" β”‚"STRING"β”‚false β”‚false β”‚false β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚"Switch" β”‚"fabric" β”‚"STRING"β”‚false β”‚false β”‚false β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚"Zone" β”‚"zonename"β”‚"STRING"β”‚false β”‚false β”‚false β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚"Host" β”‚"hostname"β”‚"STRING"β”‚false β”‚false β”‚false β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The property is called pwwn on the relationships named HZONE (Host and Zone) ans CONNECTS_TO (Host and Switch).

So your initial query would be:

MATCH (h:Host)-[h2z]->(z:Zone)
where id(h)=0
with h2z.pwwn as ref_no,h,z,h2z
MATCH (h)-[h2s]->(s:Switch)
where id(s)=118 AND h2s.pwwn = ref_no 
return h as Host,z as Zone,s as Switch, h2z,h2s;

Then, the id 118 is actually for a Storage, and not for this particular switch. This would be id 127.
Changing it,returns the host, the switch and all the zones defined in that switch that maps to this particular host. So, filtering also the Zone:

MATCH (h:Host)-[h2z]->(z:Zone)
where id(h)=0 and id(z)=320
with h2z.pwwn as ref_no,h,z,h2z
MATCH (h)-[h2s]->(s:Switch)
where id(s)=127 AND h2s.pwwn = ref_no 
return h as Host,z as Zone,s as Switch, h2z,h2s;

And now we would have this area exactly the same as in my original query. Still showing a pwwn between Host and Switch that is not defined between Host and Zone (the one that I pointed to should not appear):

Screenshot_6

I was thinking on the likes of:

where h2s.pwwn=h2z.pwwn

Wolf

Clem,

I can't figure out how to use bloom for this, but what I'm seeking is to only show a relationship if one of it's properties is also found on another relationships property.

Wolf

can you uncheck connect result nodes under settings and test it.

Please, match the exact relationship and relationship properties also.

image

1 Like

dominicvivek06's answer is better than mine. I was incorrect about the Browser always displaying relationships between the nodes. I didn't know about the setting until today.

But the essence of my description is still correct. You need to create explicit matches for the relationships and then explicitly return the relationship variables in the RETURN statement. Right now you have -[]-> which will match all the relationships instead of the one that you want.

It may be a bit tricky to specify the relationship. You might have to add more properties to the relationships or something to be able to be more specific.

We use WITH clause for the dynamic behavior and passing the result to the next query.

If you specify in the relationship along with WITH clause, the relationship values are passed, and with that you can easily get the connected nodes. Even the -[]-> can be called for the relationship needed. All of this can be performed dynamically.
I have done this many times for many complex queries.

Dominic,
Thanks! I did not know about this setting until now!

Wolf

Dominic,
My query was complete, with all relationships identified and passed through until the result, yes! I just found out that I had an error on it by not bringing the relationship between switches and just added this last match. Along with your other solution (the "connect result nodes" checkbox), this did the trick!

Thanks a lot!

Clem,
I just figured out how to use Bloom with a specific query, and yes, the result was almost ok. It helped identify an error on my original query in which I didn't explicitly matched the relationship between Switch nodes, but Bloom has a few flaws, like it's not able to change the relationship caption from "label" to "property" for instance.

Thanks, anyhow!

Great! Perhaps you can post your solution and explain your mistake. (That helps other people.)

BTW, I think that would be a good feature request: to add property as something to display in relationships.

Another thing would be to add Relationship conditional styling, which you can do with Nodes. E.g. you can change the color, size, etc. of a Node depending on its property.

Oh, it was a simple rookie mistake, when matching two different labeled nodes to nodes with same label, sometimes, the smae label node identified by both are the same, but sometimes they're not. Needed to add a MATCH between these 'n' nodes. After adding this new MATCH it worked OK. Another thing with this case is that I had to use OPTIONAL MATCH because when the 2 nodes are the same, a MATCH wouldn't work. Think I got this right, this time:

MATCH (h:Host)-[r]->(z:Zone)<-[r2]-(s:Storage) //Host-Zone-Storage (logical)
WHERE h.hostname='localhost.localdomain' //Host
and s.name='COMPELLENT' //Storage
with h,r,z,r2,s
match (w:Switch)-[r3]->(z) //Switch-Zone (logical)
with h,r,z,r2,s,r3,w
match (h)-[r4]->(w) //Host-Switch (physical path)
where r4.pwwn=r.pwwn
with h,z,s,w,r,r2,r3,r4
match (s)-[r5]->(w2:Switch) //Storage-Switch (physical path)
with h,z,s,w,w2,r,r2,r3,r4,r5
optional match (w)-[r6]-(w2) //Physical path between Switches (OPTIONAL when they're the same)
match (w2)-[r7]-(z) //Second switch-Zone (logical)
return h,z,s,w,w2,r,r2,r3,r4,r5,r7;