【问题标题】:neo4j: Return all nodes on the longest matching patchneo4j:返回最长匹配补丁上的所有节点
【发布时间】:2013-10-01 00:37:06
【问题描述】:

使用 neo4j 1.9.4 和 py2neo 1.6,我的图中有一个类似于二叉树的结构,其中每个节点最多有两个子节点。但是,该图并不完整,因此可能看起来像这样,其中“(x)”表示节点,“[y]”表示关系。

                     (root)
                     /     \
                   [0]     [1]
                   /         \
                 (0)         (1)
                /   \          \
              [0]   [1]        [1]
              /       \          \
            (00)      (01)       (11)
            /
          [0]
          /
       (000)

我在这里做了一些类似的例子:http://console.neo4j.org/r/ni6t5b(如果由于某种原因无法正常工作,您可以使用以下命令创建图表:

CREATE (node1 { name: '1' }),(node2 { name: '11' }),(node3 { name: '10' }),(node4 { name: '0' }),(node5 { name: '01' }),(node6 { name: '00' }),(node7 { name: '10' }),(root { name:'root' }), root-[:`1`]->node1, node1-[:`1`]->node2, node1-[:`0`]->node7, node2-[:`0`]->node3, root-[:`0`]->node4, node4-[:`1`]->node5, node4-[:`0`]->node6

我想返回存在于(单个)特定路径上的所有节点。

START root=node(1) 
MATCH path = root-[?:`0`]-()-[?:`0`]-()-[?:`0`]-() 
RETURN NODES(path)

(注意: let ID(root) = 1) 这将返回路径中的所有节点,即 (0)、(00) 和 (000) 但是,由于我不知道每个分支的深度,我也想查询这样的内容:

START root=node(1) 
MATCH path = root-[?:`1`]-()-[?:`1`]-()-[?:`0`]-()-[?:`0`]-() 
RETURN NODES(path)

应该返回所有可能在最长路径上的节点,即 (1) 和 (11)。事实上,这个查询并没有返回任何东西。我怎样才能做到这一点?注意:对于每条路径,我事先不知道该路径是否具有现有的端节点。我只想返回该路径上存在的所有节点。

此外,使用 py2neo (python) 自动构建此类查询的最佳方法是什么。例如,我有一个包含多个路径的列表,我需要查询其中的每个路径。每条路径都只存在于 '0' 和 '1' 中?

list_of_paths = ["0010", "101", "11", "101110"]

谢谢你们!

编辑:在这里 (http://wes.skeweredrook.com/cypher-longest-path/) 我可以找到类似的问题。但是,关系类型始终相同,这不适用于我的场景。所以我认为我不能从那里采用这个解决方案。

EDIT2: Wes 的建议并没有解决我的问题:

START root=node(1)
MATCH path=root-[:`1`|`0`*]->leaf
RETURN path

此查询返回从根节点开始的所有可能路径。我想要的是一个特定路径的节点。

EDIT3: Wes 的更新建议也没有解决我的问题。它只返回整个图形中最长的现有路径。但我想查询 specific 路径并将所有节点返回到图中不再存在路径的点。所以我可能想查询一条很长的路径,但实际上路径已经在第一个节点处停止,例如root-[1]->()-[0]->()-... 这个查询应该只返回节点 (1),因为路径在该点停止。 (节点(1)没有0类型的传出关系)

EDIT4:我试图找出一个可行的解决方案,但它很脏。

tree_root, = graph_db.create({"name": "root"}) # create a root

node_list = []
my_path = [1, 1, 0, 1, 1, 1] # path to query
len_of_path = len(my_path)

# add the corresponding number of nodes to the list and name them n0,..nX
for i in range(0,len_of_path):
    node_list.append("n"+str(i))


# construct the query string
my_query_start = 'START root=node({root_id}) MATCH (root)'
my_query_return = ' RETURN'

for i in range(0, len(node_list)):
    my_query_start += '-[?:`' + str(my_path[i]) + '`]->(' + str(node_list[i]) + ')'
    if i == len(node_list)-1:
        my_query_return += ' ' + str(node_list[i])
    else:
        my_query_return += ' ' + str(node_list[i]) + ','

# concatenate the query
complete_query = my_query_start + my_query_return
#print "complete_query:", complete_query

# execute the query
query_paths = neo4j.CypherQuery(graph_db, complete_query)
params = {"root_id" : tree_root._id}
my_list_of_nodes = query_paths.execute(**params)

#output results
print "data of my_list_of_nodes:", my_list_of_nodes.data
print "columns of my_list_of_nodes:", my_list_of_nodes.columns

请大家不要告诉我这应该是最终的解决方案 ;-)

【问题讨论】:

  • 您的控制台示例似乎无法正常工作——您可以尝试再次保存吗?

标签: python neo4j cypher py2neo


【解决方案1】:

您能否使用带有 OR 的 reltype 可变长度路径?

MATCH path=root-***put your partial pattern here***->[:`1`|`0`*]->leaf
WHERE NOT (leaf)-[:`0`|`1`]->()
RETURN path
ORDER BY length(path) DESC
LIMIT 1

我认为它解决了你的例子......但它比这更复杂吗?

【讨论】:

  • 这会从根目录返回所有可能的路径,对吧?但这不是我想要的。我想返回 特定 路径上的所有节点,尽管我无法判断此路径的结束节点是否存在
  • 我的意思是使用我的查询作为 match 部分。
  • 因此您将使用以下内容: START root=node(1) MATCH path=root-[:1|0*]->leaf RETURN path 但这肯定会返回所有可能的从根开始的路径。我只想返回一个特定路径的节点。
  • 我觉得我表达的不够清楚。您的建议提供的是完整图的最长现有路径,对吗?但我只想要 specific 路径的最长可能路径。所以一个场景是:给我可能的路径根上存在的所有节点-[1]-()-[1]-[0]-()-[1]-() .这应该返回节点 (1) 和 (11),因为路径在那里结束。希望这现在很清楚
  • 然后把你的模式放在根之后,再加上-[:1|0*]->leaf。如果您的模式可能已经是最长的,并且您想返回它,请输入*0..
猜你喜欢
  • 1970-01-01
  • 2013-01-18
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
相关资源
最近更新 更多