Gabe
Gabe

Reputation: 69

WHERE clause wants collection of collections of relationships, but I can only provide a collection of relationships

I am trying to query the neighborhood at a certain distance around a topic node. The twist, is I do not want to follow relationships from nodes with a certain attribute. Any query needs to run on graphs in the millions of nodes and edges (which rules out collecting paths).

I think I have a query that will do it:

MATCH (topic: attribute)-[r:describedBy|influences*0..2]-(n: attribute) 
WHERE id(topic) IN [239930]
WITH n, r as rels, topic
MATCH (n: attribute)-[r:describedBy|influences]->()
WHERE NOT n.key in ['enrichment', 'classification'] AND r in rels
WITH n, r, collect(r) as rels, topic
MATCH path = shortestpath((topic)-[*..2]-(n))
WHERE extract(rel IN rels(path) | rel) as r WHERE r in rels 
WITH r, extract(n IN nodes(path) | n) as nodes
RETURN count(DISTINCT r), count(DISTINCT nodes)

The problem is trying to compare collections of relationships. Specifically:

Type mismatch: expected Collection<Collection<Relationship>> but was Collection<Relationship> (line 8, column 43 (offset: 369))
"WHERE extract(rel IN rels(path) | rel) in rels "

I have run into this 'collection of collection of relationships' problem in multiple attempts to create this query.

How can I either A: fix the collection of collection of relationships problem or B: rewrite the query such that it returns the neighborhood around one or more nodes at a given distance and without following relationships from nodes with specific properties?

[EDIT] Based on @cybersam's recommendation, the query is now: WHERE NOT n.key in ['enrichment', 'classification'] AND r in rels WITH n, r, collect(r) as rels, topic MATCH path = shortestpath((topic)-[*..2]-(n)) WHERE [r2 IN rels(path) WHERE r2 in rels] WITH r, extract(n IN nodes(path) | n) as nodes RETURN count(DISTINCT r), count(DISTINCT nodes) The problem is that this returns 47242 relationships and 47242 edges. It would appear it's returning the edges from the collection of path rather than from the sub-query above, (which has a count of 100103 edges or so from previous experimentation).

Upvotes: 1

Views: 105

Answers (1)

cybersam
cybersam

Reputation: 66957

First of all, you have syntax errors in this line of your question's query:

WHERE extract(rel IN rels(path) | rel) as r WHERE r in rels

You probably actually used WITH instead of the leading WHERE -- as that would result in the error you reported:

WITH extract(rel IN rels(path) | rel) as r WHERE r in rels

Now, assuming that I am correct above:

  1. The result of extract(rel IN rels(path) | rel) is the same as rels(path), which makes using extract() a waste of time. I suspect that you actually meant to extract something else. Note that, currently, the resulting r is a collection of relationships.
  2. Since r is a collection of relationships, the r in rels clause would require that rels be a collection of collection of relationships. But it is actually a collection of relationships, hence the error.

The solution might be as easy as fixing your extract() clause. I don't know enough about your problem domain to know how to do that, but hopefully this is enough to point you in the right direction.

[EDIT]

Based on the clarification from @Gabe, this might be the correct replacement for the line in question:

WHERE all(r IN rels(path) WHERE r in rels)

Upvotes: 1

Related Questions