Pergunta

I'm trying to write a query that will return nodes that either match a node property or a relationship property.

For instance, I want all nodes where the name property is George OR if the relationship property status is "good". I have two queries that will get the nodes for each of these:

MATCH (n) where n.name = 'George' return n

MATCH (n)-[r]-() where r.status = 'good' return n 

Is there a singe query I could write to get these combined results? I thought I could use this optional query (below), but I seemed to have misunderstood the optional match clause because I'm only getting nodes from the first query.

MATCH (n) where n.name = 'George' 
Optional MATCH (n)-[r]-() where r.status = 'good' return distinct n 
Foi útil?

Solução

By the time the optional match happens, the only n nodes that are around to make the optional match from are the ones that already match the first criteria. You can do

MATCH (n)
WHERE n.name = 'George' OR n-[{ status:"good" }]->()
RETURN n

but for larger graphs remember that this will not make efficient use of indices.

Another way would be

MATCH (n {name:"George"})
RETURN n
UNION MATCH (n)-[{status:"good"})->()
RETURN n

This should do better with indices for the first match, assuming you use a label and have the relevant index set up (but the second part would still potentially be very inefficient).

Edit
Re comment, relationship indexing would make that part faster, correct, but to my mind it would be better to say it is slow because the pattern is underdetermined. The second match pattern does something like

  • bind every node in the graph to (n)
  • get all outgoing relationships (regardless of type) from (n)
  • check relationship for status="good"

You could improve performance with relationship indexing, but since a relationship exists only between the two nodes it relates, you can think of it instead as indexed by those nodes. That is, fix the first bullet point by excluding nodes whose relationships are not relevant. The two match clauses could look like

MATCH (n:Person {name:"George"})  
       // add label to use index
MATCH (n:Person)-[{status:"good"}]->() 
       // add label to limit (n) -no indexing, but better than unlimited (n)
MATCH (n:Person {name:"Curious"})-[{status:"good"}]->()
       // add label to use index -now the relationships are sort-of-indexed

and/or type the relationship

MATCH (n)-[:REL {status:"good"}]->() // add type to speed up relationship retrieval

in fact, with anonymous relationships and rel property, it would probably make sense (bullet point three) to make the property the type, so

MATCH (n)-[:GOOD]->() // absent type, it would make sense to use the property as type instead

Your actual queries may look very different, and your question wasn't really about query performance at all :) oh well.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top