Search code examples
memgraphdb

How to return nothing if the results of an optional match do not meet certain conditions in Memgraph?


I'm currently working on a task that involves a specific type of query in a graph database. The task requires me to perform an optional match operation, which is designed to retrieve nodes and relationships that may or may not exist in the database.

If the optional match operation does find data, I don't want the query to return those results unconditionally. Instead, the results must fulfill certain specific conditions before they're included in the final output. In other words, even though the data matching the optional match clause might exist, I want my query to effectively act as if it doesn't, unless the data also meets some additional criteria. If the retrieved data does not meet these criteria, the overall query should not return a result.

Is this something that can be achieved?

I've started with this code:

MATCH (originServer:Server{ip:'192.168.0.1'})-[link]->(trafficLimit:BandwidthCap) 
MATCH (trafficLimit)-[endLink:Dest]->(destinationServer:Server{ip:'192.168.0.2'})
OPTIONAL MATCH (trafficLimit:BandwidthCap)-[viaPath:Via]->(intermediateRouter:Router)
WHERE (intermediateRouter IS NULL) OR any(i in ['Cisco'] where i = intermediateRouter.brand)
RETURN originServer, link, trafficLimit, endLink, destinationServer, viaPath, intermediateRouter;

After additional tweaking, I've arrived at this - but it only returns the NULL from the ELSE section - can't figure out why.

MATCH (originServer:Server{ip:'192.168.0.1'})-[link]->(trafficLimit:BandwidthCap) 
MATCH (trafficLimit)-[endLink:Dest]->(destinationServer:Server{ip:'192.168.0.2'})
OPTIONAL MATCH (trafficLimit:BandwidthCap)-[viaPath:Via]->(intermediateRouter:Router)
OPTIONAL MATCH (trafficLimit:BandwidthCap)-[exceptPath:Via]->(exceptionRouter:Router)
RETURN
CASE trafficLimit
WHEN intermediateRouter IS NULL AND exceptionRouter IS NULL THEN trafficLimit.cap
WHEN intermediateRouter = "Cisco" THEN trafficLimit.cap
ELSE NULL
END

Solution

  • Looking over your problem, it appears to me that the error originates from the relationship exceptPath in your query, which you seem to have unintentionally assigned as a :Via type, instead of the correct :ExceptVia type. This misclassification would cause the condition to meet the criteria consistently, resulting in a perpetual 'true' evaluation. To resolve this issue, I would suggest revising the relationship to its correct type :ExceptVia. After making this adjustment, your code should function as expected. Here is how the corrected version might look:

    MATCH (originServer:Server{ip:'192.168.0.1'})-[link]->(trafficLimit:BandwidthCap)
    MATCH (trafficLimit)-[endLink:Dest]->(destinationServer:Server{ip:'192.168.0.2'})
    OPTIONAL MATCH (trafficLimit:BandwidthCap)-[viaPath:Via]->(intermediateRouter:Router)
    OPTIONAL MATCH (trafficLimit:BandwidthCap)-[exceptPath:ExceptVia]->(exceptionRouter:Router)
    RETURN
    CASE
      WHEN intermediateRouter IS NULL AND exceptionRouter IS NULL THEN trafficLimit.cap
      WHEN exceptionRouter IS NULL AND any(n in ['Cisco'] WHERE n = intermediateRouter.brand) THEN trafficLimit.cap, trafficLimit.id
      WHEN intermediateRouter IS NULL AND NOT any(n in ['Cisco'] WHERE n = exceptionRouter.brand) THEN trafficLimit.cap
    ELSE NULL
    END
    AS cap
    

    This Cypher query takes into account the revised relationship type.