Reputation: 379
I am a newbie in neo4j and no doubt i am loving it.
Now my query is i have a database in which there are users who have visited one or more than one urls and these urls contain one or more than one tags.
Now what i want is to retrieve tags for a certain user who has visited more than one urls.
the relation is somewhat like this:
(:User)-[:VISITED]->(:URL)-[:CONTAINS]->(:Tag)
Now i want to retrieve user who has visited more than one urls and all the tags contained in all those urls. So basically i want all the tags that a user has visited where visited urls are more than one.
Upvotes: 2
Views: 87
Reputation: 22171
Using Cypher 2.X, this should make the job:
MATCH (user:User)
MATCH user-[:VISITED]->(url:URL)
WITH count(url) AS countUrl, url
WHERE countUrl > 1
MATCH url-[:CONTAINS]->(tag:Tag)
RETURN user.id, collect(tag) AS tags //you can show whatever you want here
Upvotes: 3
Reputation: 20185
You can still optimize the query provided by Mik378.
In fact, in Cypher you can reproduce the java equivalent of getDegree
with the size(pattern) clause :
MATCH (n:User)-[:VISITED]->(url)<-[:TAGS]-(tag:Tag)
WHERE size((n)-[:VISITED]->()) > 1
RETURN n.email, collect(distinct tag.name) as tags
which would result in the following query plan :
+------------------+---------------+------+--------+------------------------------------------+----------------------------------------------------+
| Operator | EstimatedRows | Rows | DbHits | Identifiers | Other |
+------------------+---------------+------+--------+------------------------------------------+----------------------------------------------------+
| EagerAggregation | 3 | 5 | 90 | n.email, tags | n.email |
| Projection | 7 | 24 | 48 | anon[15], anon[37], n, n.email, tag, url | n.email; tag |
| Filter(0) | 7 | 24 | 24 | anon[15], anon[37], n, tag, url | tag:Tag |
| Expand(All)(0) | 7 | 24 | 34 | anon[15], anon[37], n, tag, url | (url)<-[:TAGS]-(tag) |
| Filter(1) | 3 | 10 | 10 | anon[15], n, url | url:Url |
| Expand(All)(1) | 3 | 10 | 15 | anon[15], n, url | (n)-[:VISITED]->(url) |
| Filter(2) | 2 | 5 | 10 | n | GetDegree(n,Some(VISITED),OUTGOING) > { AUTOINT0} |
| NodeByLabelScan | 5 | 5 | 6 | n | :User |
+------------------+---------------+------+--------+------------------------------------------+----------------------------------------------------+
Total database accesses: 237
The query was with my test db, so for your current implementation, it should be :
MATCH (n:User)-[:VISITED]->(url)-[:CONTAINS]->(tag:Tag)
WHERE size((n)-[:VISITED]->()) > 1
RETURN n.email, collect(distinct tag.name) as tags
Upvotes: 3