搜索链接节点的任意群集Neo4j

时间:2016-12-07 14:27:52

标签: neo4j cypher

我是neo4j的新手。我已经设置了一个包含大约200个节点的基本数据库,其中包括人员,地址和电话号码。

他们都可以相互链接,因此一个人可以拥有与他们相关联的电话号码和地址,但地址可以连接到电话号码,电话号码可以链接到电话号码,人们可以链接到人,等

我希望能够搜索节点集群,例如我想要返回所有连接的节点,例如:

  • 一个人的名字叫詹姆斯,
  • 另一个人姓jones,
  • 包含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

我一无所获。

我要问的是,我知道这个人,联系和地址,他们是否以任何方式联系?

2 个答案:

答案 0 :(得分:0)

这些查询可能会让您入门。

除此之外:我建议您针对不同类型的关系使用不同的关系类型(例如HAS_ADDRESSHAS_CONTACTKNOWS)。这将使您的查询更容易理解,并最终可以帮助您加快查询速度(因为您可以简化它们)。

  1. 要查找任何姓氏为“James”的人,他以任何方式与以“0123”开头的联系人相关联:

    MATCH path=(p:person)-[*]-(c:contact) 
    WHERE
      p.Surname = "James"   AND 
      c.Contact =~ "0123.*"
    RETURN p,c
    
  2. 要查找任何姓氏为“James”且以任何方式连接到以“0123”开头的联系人的人,只要他们之间的路径包含邮政编码为“ab11ab”的地址:< / p>

    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
    
  3. 要查找任何姓氏为“James”的人,他们以任何方式与邮政编码为“ab11ab”的地址相关联,只要他们之间的路径包含以“0123”开头的联系人:< / p>

    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
    
  4. 找到任何姓氏“詹姆斯”的人,他们以任何方式连接到邮编为“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
    

答案 1 :(得分:0)

如果我理解正确,那么你应该获得一系列必需的节点,然后找到所有人与所有人连接的路径。

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