【问题标题】:Returning the Heaviest path (with the highest sum of a given property in all of it's relations) from a node to all of its leafs返回从节点到其所有叶子的最重路径(在所有关系中给定属性的总和最大)
【发布时间】:2019-04-30 11:04:02
【问题描述】:

有没有办法编写一个 Cypher 查询,该查询返回从给定节点到其叶子节点的所有现有路径中所有(选定)关系属性总和最高的路径?

你好, 首先我要说明我是如何创建图表的:

CREATE CONSTRAINT ON (j:JOB) ASSERT j.order_id IS UNIQUE

USING PERIODIC COMMIT 1000
//EXPLAIN
LOAD CSV WITH HEADERS FROM "file:///jobs.csv" AS row
MERGE (j:JOB {order_id: row.child_order_id})
SET j.job_name = row.child_job_name,
    j.job_owner = row.child_job_owner,
    j.group_name = row.child_group_name,
    j.order_time = row.child_order_time,
    j.start_time = row.child_start_time,
    j.end_time = row.child_end_time;

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:///child_father.csv" AS row
MATCH (c:JOB {order_id: row.child_order_id})
MATCH (f:JOB {order_id: row.father_order_id})
MERGE (c)-[d:DEPENDS_ON]->(f)
SET d.elapsed_min = row.elapsed_min;

现在,我的目标是将给定订单 ID 中关系属性“elapsed_min”总和最大的路径返回到它所依赖的所有叶节点。

由于我在 Cypher 中找不到这样做的方法,因此我尝试使用 py2neo 库在 python 上进行操作。 起初我尝试使用普通的 Dijksta 算法来返回最轻的路径,在我能做到之后我会改变算法以返回最重的路径

所以我做了这个:

import py2neo
from py2neo import Graph
from py2neo import Node, Relationship

NEO4J_URI = "bolt://127.0.0.1:7687"
NEO4J_USER = "neo4j"
NEO4J_PASSWORD = "neo4j"

graph = Graph(NEO4J_URI, auth = (NEO4J_USER, NEO4J_PASSWORD), bolt = True)

def dijkstra(graph,start,goal):
    shortest_distance = {}
    predecessor = {}
    unseenNodes = graph
    infinity = 999999
    path = []

    for node in unseenNodes:
        shortest_distance[node] = infinity
    shortest_distance[start] = 0

    while unseenNodes:
        minNode = None
        for node in unseenNodes:
            if minNode is None:
                minNode = node
            elif shortest_distance[node] < shortest_distance[minNode]:
                minNode = node

        for childNode, weight in graph[minNode].items():
            if weight + shortest_distance[minNode] < shortest_distance[childNode]:
                shortest_distance[childNode] = weight + shortest_distance[minNode]
                predecessor[childNode] = minNode

        unseenNodes.pop(minNode)

    # get the path
    currentNode = goal
    while currentNode != start:
        try:
            path.insert(0,currentNode)
            currentNode = predecessor[currentNode]
        except KeyError:
            print("Path not reachable")
            break

    if shortest_distance[goal] != infinity:
        print('Shortest distance is: ' + str(shortest_distance[goal]))
        print('And the path is: ' + str(path))

现在我需要找到一种方法以这种 json 格式返回路径,这样我就可以在其上运行 Dijkstra 算法,如下所示:

testGraph = {'a':{'b':10,'c':3},'b':{'c':1,'d':2},'c':{'b':4,'d':8,'e':2},'d':{'e':7},'e':{'d':9}}
#the relation property that means the distance from node: a to b is 10, a to c is 3, b to c is 1 and so on...

dijkstra(testGraph, 'a', 'd')

#the output is: Shortest distance is: 9
#               And the path is: ['c', 'b', 'd']

但我不确定如何返回正确的路径以及哪种格式最适合.. 这就是我所拥有的,我无法将其发送到我的算法:

testGraph = graph.run(   "MATCH (c:JOB)-[d:DEPENDS_ON*]->(f:JOB) "
                    "WHERE c.order_id = '4p0ta' "
                    "RETURN * "
                    "LIMIT 50").to_table()#data() #to_subgraph #to_data_frame()

【问题讨论】:

    标签: python neo4j cypher dijkstra py2neo


    【解决方案1】:

    此 Cypher 查询应返回总和最高的路径(在叶节点处结束):

    MATCH p=(c:JOB)-[:DEPENDS_ON*]->(f:JOB)
    WHERE c.order_id = '4p0ta' AND NOT (f)-[:DEPENDS_ON]->()
    RETURN p, REDUCE(s = 0, d IN RELATIONSHIPS(p) | s + d.elapsed_min) AS total
    ORDER BY total DESC
    LIMIT 1
    

    请注意,如果您的路径很长和/或您的节点有很多关系,variable-length relationships 可能会非常昂贵(即,需要很长时间甚至内存不足)。您可能需要设置长度上限才能使用此查询。

    【讨论】:

    • 谢谢,它确实有很大帮助。此查询如何处理路径中的依赖循环?
    • 也可以在neo4j图算法中查看最大生成树算法a
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多