如何使用 Cypher 获取与多个节点相关的节点,这些节点又与 Neo4j 中的多个节点相关

How to get nodes that are realted to more than one node which in turn are related to more than one node in Neo4j using Cypher

我是 neo4j 的新手,毫无疑问我很喜欢它。

现在我的查询是我有一个数据库,其中有访问过一个或多个 url 的用户,并且这些 url 包含一个或多个标签。

现在我想要的是为访问过多个 url 的某个用户检索标签。

关系有点像这样:

(:User)-[:VISITED]->(:URL)-[:CONTAINS]->(:Tag)

现在我想检索访问过多个网址的用户以及所有这些网址中包含的所有标签。所以基本上我想要一个用户访问过的所有标签,其中访问过的 url 不止一个。

使用 Cypher 2.X,这应该可以完成工作:

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

您仍然可以优化 Mik378 提供的查询。

事实上,在 Cypher 中,您可以使用 size(pattern) 子句重现 getDegree 的 java 等价物:

MATCH (n:User)-[:VISITED]->(url)<-[:TAGS]-(tag:Tag)
WHERE size((n)-[:VISITED]->()) > 1
RETURN n.email, collect(distinct tag.name) as tags

这将导致以下查询计划:

+------------------+---------------+------+--------+------------------------------------------+----------------------------------------------------+
|         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

查询是针对我的测试数据库的,因此对于您当前的实现,它应该是:

MATCH (n:User)-[:VISITED]->(url)-[:CONTAINS]->(tag:Tag)
WHERE size((n)-[:VISITED]->()) > 1
RETURN n.email, collect(distinct tag.name) as tags