具有相同节点属性的密码缩小搜索

时间:2018-04-09 03:34:12

标签: neo4j cypher

我的问题在于:cypher-how-get-relation-between-every-two-node-and-the-distance-from-start-node,更多细节:200万家公司,每家公司必须且只属于一家名为group的领先公司,因此每个节点都有属性:groupId和companyId;更重要的是,不同群体的公司可能有关系。问题:给定groupId和领先的公司ID,返回该组中的所有关系以及该组中与领先公司最短距离的每个节点。

由于sw表示anwser有很大的性能问题,特别是shortPath一个,所以我的问题是我们可以在使用shortPath时缩小搜索范围,只搜索具有相同属性的节点吗?

还是有其他办法解决原来的问题吗?

抱歉,因为我在中国大陆,无法访问console.neo4j.com(即使使用VPN),所以我把样本放在这里:

create (a :COMPANY {companyId:"a",groupId:"ag"}),
       (b:COMPANY  {companyId:"b",groupId:"ag"}),
       (c:COMPANY  {companyId:"c",groupId:"ag"}),
       (d:COMPANY {companyId:"d",groupId:"ag"}),
       (e:COMPANY  {companyId:"e",groupId:"eg"})
create (a)-[:INVESTMENT]->(b),
       (b)-[:INVESTMENT]->(c),
       (c)-[:INVESTMENT]->(d),
       (a)-[:INVESTMENT]->(c),
       (d)-[:INVESTMENT]->(b),
       (c)-[:INVESTMENT]->(e) 
return *

此处节点a,b,c,d是同一个群组,a是领先公司,e是另一个群组,但与c有关系。所以我想在ag组中获取节点 - 节点关系,例如:a-b,a-c,b-c,c-d,d-b以及从a到组成员的最短距离,例如,返回dist.a=0,dist.b=1,dist.c=1,dist.d=2

3 个答案:

答案 0 :(得分:0)

我认为在纯密码的帮助下无法解决这个问题。您可以通过向关系添加临时属性并应用Dijkstra algorithm来尝试使用APOC库。

输入参数:

{
  "groupId": "ag",
  "leadingCompany": "a"
}

查询:

// Search for a leading company
MATCH (lc:COMPANY {companyId: $leadingCompany, groupId: $groupId})
WITH lc, 
     apoc.create.uuid() as tmpProp // Temporary property name

// All relationships in the group are found. 
// And the value of the temporary property is set ..
MATCH (c1:COMPANY {groupId: $groupId})-[r:INVESTMENT]->(c2:COMPANY {groupId: $groupId})
CALL apoc.create.setRelProperty(r, tmpProp, 1) yield rel
WITH lc, tmpProp, 
     count(r) as tmp

// For each node in the group, need to find short paths to the leading company
MATCH (c:COMPANY {groupId: $groupId})
CALL apoc.algo.dijkstraWithDefaultWeight(lc, c, 'INVESTMENT', tmpProp, 2000000) yield path
WITH tmpProp, c, 
     min(length(path)) as distanceToLeading

// All paths in the group are found, and the temporary property is deleted
MATCH (c)-[r:INVESTMENT]->(:COMPANY {groupId: $groupId})
CALL apoc.create.removeRelProperties(r, [tmpProp]) yield rel
RETURN c as groupNode, distanceToLeading, 
       collect(r) as groupRelations

答案 1 :(得分:0)

APOC程序可以在这里提供帮助,因为一些路径扩展程序可用于查找到组中每个节点的最短距离,还有一个cover()程序可以找到所有一组节点之间的关系。

您希望确保首先拥有索引:公司(groupId)和:公司(companyId)。

MATCH (c:Company{groupId:$groupId})
WITH collect(c) as companies
WITH companies, [c in companies | id(c)] as companyIds, [c in companies 
 WHERE NOT (c)<-[:INVESTMENT]-(:Company{groupId:$groupId})][0] as lead
// for the above, if you already know the lead companyId, just MATCH to the lead instead of this filter
CALL apoc.algo.cover(companyIds) YIELD rel
WITH companies, lead, collect(rel {start:startNode(rel).companyId, end:endNode(rel).companyId}) as relationships
UNWIND companies as company
MATCH path = shortestPath((lead)-[:INVESTMENT*]->(company))
WHERE all(node in nodes(path) WHERE node in companies)
RETURN relationships, collect(company {.companyId, distance:length(path)}) as distance

答案 2 :(得分:0)

此查询将为您提供所需的输出:

 match p=((c:COMPANY{companyId:'a'})-[i:INVESTMENT*0..99]->(l:COMPANY)) 
    where l.groupId=c.groupId 
    with c,i,l,nodes(p) as path  order by c.companyId
    with c,l,collect(distinct l.companyId) as Companies,min(size(path))-1 as Dist
    match pp=shortestpath((cc:COMPANY{companyId:'a'})-[ii:INVESTMENT*0..99]->(ll:COMPANY)) 
    where ll.companyId in Companies
    with c,Companies,Dist,reduce(s='',x in nodes(pp)|s + x.companyId ) as CompanyPath     
return c.companyId,Companies,Dist,CompanyPath order by Dist

您会注意到,它不需要有关groupId的高级知识。如果牵头公司可以分为两组,则需要将其包含在最初的位置。