我是neo4j的新手。我已经设置了一个基本的DB,其中大约有200个节点,这些节点包括其他人,地址和电话号码。
他们都可以互相链接,因此一个人可以拥有与他们关联的电话号码和地址,但是可以将地址连接到电话号码,电话号码可以链接到电话号码,与人,人们,人们,人,等
我希望能够搜索一个节点群,例如我想返回任何连接的节点,例如:
- 一个人的姓詹姆斯,
- 另一个人有琼斯的姓氏,
- 一个包含123456的电话号码
- AB11AB邮政编码的地址
可以找到上述多个结果,我想找到一个群集,该群集至少链接上述每个结果(最初是1级,但最终可配置的级别)。我不在乎它们是如何链接的。
此外,可能有4个以上的项目需要搜索(用户配置)
。我已经尝试单独搜索它们,然后尝试将它们结合并将它们集合在一起,但是我似乎无法正确地掌握逻辑。
一些返回相关节点的简单查询(以了解我的数据):
MATCH (p:person {Surname:"james"}) RETURN a
MATCH (a:address {Postcode:"ab11ab"}) RETURN p
这是可能的吗?
任何帮助都将受到欢迎。
谢谢,
乔恩
群集可能不是最好的术语,也许是sub Graph ??
这是场景:
CREATE (I1:person {description:'John James', FirstName:'John', Surname:'James'})
CREATE (I2:address {description:'1 Test Street ab11ab', Postcode:'ab11ab'})
CREATE (I3:contact {description:'01234567890 home telephone', Contact:'01234567890'})
CREATE (I4:person {description:'Frank James', FirstName:'Frank', Surname:'James'})
CREATE (I5:contact {description:'01234567899 home telephone', Contact:'01234567899'})
CREATE (I6:person {description:'Bert James', FirstName:'Frank', Surname:'James'})
CREATE (I7:person {description:'Brenda James', FirstName:'Brenda', Surname:'James'})
CREATE (I8:person {description:'Violet James', FirstName:'Violet', Surname:'James'})
CREATE (I9:address {description:'75 Test Street ab11ab', Postcode:'ab11ab'})
CREATE (I1)-[:LinkedTo]->(I2)
CREATE (I2)-[:LinkedTo]->(I3)
CREATE (I4)-[:LinkedTo]->(I5)
CREATE (I6)-[:LinkedTo]->(I7)
CREATE (I7)-[:LinkedTo]->(I8)
CREATE (I7)-[:LinkedTo]->(I9)
如果我运行以下内容:
MATCH (p:person)--(a:address)--(c:contact)
where p.Surname = "James" AND
a.Postcode = "ab11ab" AND
c.Contact =~ "0123.*"
RETURN p,a,c
我得到了我想要的群集。但是,如果我更改链接的顺序:
MATCH (p:person)--(c:contact)--(a:address)
where p.Surname = "James" AND
a.Postcode = "ab11ab" AND
c.Contact =~ "0123.*"
RETURN p,a,c
我什么都没得到。
我问的是我认识这个人,联系和地址,他们是否以任何方式链接?
如果我正确理解,那么您应该得到一系列所需的节点,然后找到所有与每个人都连接的路径。
// Get an array of all matching nodes:
OPTIONAL MATCH (p:person {Surname: "James"})
WITH COLLECT(p) AS c1
OPTIONAL MATCH (a:address {Postcode:"ab11ab"})
WITH COLLECT(a)+c1 AS c2
OPTIONAL MATCH (c:contact) WHERE c.Contact =~ "0123.*"
WITH COLLECT(c)+c2 AS nodes
// Take the Cartesian product:
UNWIND nodes AS n1
UNWIND nodes AS n2
// Get path:
MATCH p = (n1)-[*]-(n2)
WHERE ANY(n IN nodes WHERE n IN NODES(p) AND NOT n IN [n1,n2])
RETURN p
这些查询可能会让您开始。
一边:我建议您使用不同类型的关系使用不同的关系类型(例如HAS_ADDRESS
,HAS_CONTACT
和KNOWS
)。这将使您的查询更容易理解,并最终可以帮助您加快查询(因为您可以简化它们)。
-
找到任何姓氏"詹姆斯"的人,他们以任何方式连接到以" 0123"开头的联系人:
MATCH path=(p:person)-[*]-(c:contact) WHERE p.Surname = "James" AND c.Contact =~ "0123.*" RETURN p,c
-
找到任何姓氏"詹姆斯"的人,他们以任何方式连接到以" 0123"开头的联系人,只要它们之间的路径包括一个地址,其邮政编码为" ab11ab":
MATCH path=(p:person)-[*]-(c:contact) WHERE p.Surname = "James" AND c.Contact =~ "0123.*" AND ANY(n IN NODES(path)[1..-1] WHERE 'address' IN LABELS(n) AND n.Postcode = "ab11ab") RETURN p,c
-
找到任何姓氏"詹姆斯"的人,他们以任何方式连接到邮政编码为" ab11ab"的地址,只要他们之间的路径包括一个以" 0123"开头的联系人:
MATCH path=(p:person)-[*]-(a:address) WHERE p.Surname = "James" AND a.Postcode = "ab11ab" AND ANY(n IN NODES(path)[1..-1] WHERE 'contact' IN LABELS(n) AND n.Contact =~ "0123.*") RETURN p,a
-
找到任何姓氏"詹姆斯"的人,他们以任何方式连接到邮政编码为" ab11ab"的地址,并且接触以" 0123"开头(这很可能在大的情况下很慢。DB):
MATCH (p:person {Surname: "James"}) OPTIONAL MATCH path1 = (p)-[*]-(c:contact) WHERE c.Contact =~ "0123.*" WITH p, c, [n IN NODES(path1)[1..-1] WHERE 'address' IN LABELS(n) AND n.Postcode = "ab11ab"] AS addrs OPTIONAL MATCH path2 = (p)-[*]-(a:address) WHERE a.Postcode = "ab11ab" WITH p, c, addrs + a AS addrs, [n IN NODES(path2)[1..-1] WHERE 'contact' IN LABELS(n) AND n.Contact =~ "0123.*"] AS conts WITH p, addrs, conts + c AS conts UNWIND conts AS cont WITH p, addrs, COLLECT(DISTINCT cont) AS conts WHERE SIZE(conts) > 0 UNWIND addrs AS addr WITH p, conts, COLLECT(DISTINCT addr) AS addrs WHERE SIZE(addrs) > 0 RETURN p, conts, addrs