Shortest k is fast, but I don't understand how it works[Revised!]

I used the graph from the following link:

Two queries returned different results and had quite different times!

< query 1 >
match (m:Machine{name:'DC1-RCK-1-2-M-3'}), (m2:Machine{name:'DC1-RCK-1-4-M-45'})
match path = shortest 300 (m)-[:!TYPE&!HOLDS]-+(m2)
where not any(node in nodes(path) where 'DataCenter' in labels(node) or 'Version' in labels(node))
return count()
count(
)
7
15624 ms ==> time was changed. see my reply below.

< query 2 >
match (m:Machine{name:'DC1-RCK-1-2-M-3'}), (m2:Machine{name:'DC1-RCK-1-4-M-45'})
match path = shortest 300 (m)--+(m2)
where not any(node in nodes(path) where 'DataCenter' in labels(node) or 'Version' in labels(node))
and not any(rel in relationships(path) where type(rel) in ['TYPE', 'HOLDS'])
return count()
count(
)
3
800 ms

The first query finds the 300 shortest paths that do not have TYPE and HOLDS. Path are filtered on expansion, before shortest is applied.
The second query finds 300 shortest paths between the 2 end nodes, then throws out the paths that have TYPE and HOLDS. Paths are post-filtered.

That is not the same. The second query could return 300 shortest paths, all of them including TYPE and/or HOLDS, and then throw them all away in the following filter. It might ignore other paths that might be a bit longer, but not include TYPE/HOLDS.
The first query will only consider for shortest the paths that obey the filter.

You should not expect the same results, they are different queries.

1 Like

Thank you for your reply and kind explanations.
I also found that the first query executes at once when I index for (m:Machine) on m.name.