我正在使用 ArangoDB,并且有一个图形遍历场景,其中我需要根据属性跳过特定节点,但仍然推断其他两个节点之间的间接连接(边)。我的图包含从 A 到 B 和 B 到 C 的边,但不直接从 A 到 C。节点 B 有一个属性 `ShouldSkip` 设置为 true,我想在遍历结果中跳过它。
期望的结果是获得边:从 A 到 C 的边(推断),以及节点:A 和 C,在结果中有效地跳过 B。但是,由于图中没有从 A 到 C 的直接边,所以我不确定如何在查询结果中表示这一点。
这是我当前的 AQL 查询:
LET startNodeId = 'A' // Example start node
LET depth = 2
LET startNode = DOCUMENT('nodeCollectionName', startNodeId)
LET traversalResults = (
FOR v, e IN 1..depth OUTBOUND startNode GRAPH 'graphName'
FILTER v.ShouldSkip != true
LIMIT 100
RETURN {node: v, edge: e}
)
LET allNodes = (
FOR tr IN traversalResults
RETURN tr.node
)
LET allEdges = (
FOR tr IN traversalResults
RETURN tr.edge
)
RETURN {StartNode: startNode, Nodes: UNIQUE(FLATTEN(allNodes)), Edges: UNIQUE(FLATTEN(allEdges))}
如何调整此查询以推断从 A 到 C 的边缘(仅!没有 A 到 B 和 B 到 C),或者是否有更好的方法在 ArangoDB 中实现此目的(例如在索引中创建 A 的虚拟边缘)到 C - 不太可取)?
实际上我希望得到的答复是: 节点:[A,C] 边缘:[{_from:A,_to:C}]
如果您有这样的图表:
A ──> B ──> C
(X)
并且你想要推断(跳过节点 B):
A ──> C
您需要修改 AQL 查询来执行条件遍历。
关键是收集路径,然后根据
ShouldSkip
属性未设置为 true 的节点手动构造要包含的边。
LET startNodeId = 'A' // Example start node
LET depth = 2
LET startNode = DOCUMENT('nodeCollectionName', startNodeId)
LET paths = (
FOR v, e, p IN 1..depth OUTBOUND startNode GRAPH 'graphName'
FILTER p.vertices[*].ShouldSkip ALL != true // Filter out paths containing nodes with ShouldSkip == true
RETURN p
)
LET inferredEdges = (
FOR path IN paths
LET sourceNode = path.vertices[0] // The source node A
LET targetNode = LAST(path.vertices) // The target node C
FILTER sourceNode.ShouldSkip != true AND targetNode.ShouldSkip != true // Ensure neither A nor C should be skipped
RETURN { _from: sourceNode._id, _to: targetNode._id }
)
RETURN {
StartNode: startNode,
Nodes: [startNode._key, (FOR edge IN inferredEdges RETURN DOCUMENT(edge._to)._key)], // Assuming _key is used as the node identifier
Edges: inferredEdges
}
paths
收集从起始节点到指定深度的所有路径,确保路径中的任何节点都不应被跳过。inferredEdges
构造从路径中的第一个节点到最后一个节点的边,前提是 ShouldSkip
属性都没有设置为 true。
即使图中没有从 A 到 C 的直接边,只要存在一条不包含任何应跳过的节点的路径,您就可以推断出一条边。
这应该会给你你想要的结构,节点 B 被排除在输出之外。
嗨@VonC,谢谢,不知道为什么我们需要 FILTER p.vertices[*].ShouldSkip ALL != true 在路径部分。
FILTER p.vertices[*].ShouldSkip ALL != true
部分中过滤器paths
的用途是确保返回的任何路径不包含任何将ShouldSkip
属性设置为true
的顶点(节点)。
但是,您实际上可能只想跳过节点 B,但仍想推断节点 A 和 C 之间的连接。
在这种情况下,应调整
paths
部分中的过滤条件以允许路径通过节点 B,但仍将节点 B 从最终结果中排除。
以下是查询所需的调整:
LET paths = (
FOR v, e, p IN 1..depth OUTBOUND startNode GRAPH 'graphName'
FILTER v.ShouldSkip != true OR v._id == startNode._id // Allow the startNode even if it should be skipped
COLLECT sourceNode = p.vertices[0], targetNode = LAST(p.vertices) INTO
group KEEP p
FILTER LENGTH(group) > 0 // Make sure we have at least one valid path
LET validPaths = (
FOR g IN group
LET path = g.p
FILTER path.vertices[1].ShouldSkip != true // Check the second node in the path
RETURN path
)
FILTER LENGTH(validPaths) > 0 // We have a path that does not include skipped nodes except the start
RETURN { _from: sourceNode._id, _to: targetNode._id }
)
LET inferredEdges = (
FOR path IN paths
RETURN { _from: path._from, _to: path._to }
)
RETURN {
StartNode: startNode,
Nodes: [startNode._key, (FOR edge IN inferredEdges RETURN DOCUMENT(edge._to)._key)],
Edges: inferredEdges
}
FILTER
子查询中的paths
语句现在允许路径包含startNode(在您的情况下为A),即使根据ShouldSkip
属性应该跳过它,但它确保路径中的第二个节点(B) 不被跳过。ShouldSkip
节点的路径仍被排除。
COLLECT
语句用于按起始节点和结束节点对路径进行分组,然后对于每个组,它会过滤掉任何不符合排除ShouldSkip
节点条件的路径。LET inferredEdges
部分根据过滤的路径创建您想要包含在结果中的边缘。 LET validPaths
内循环过滤掉直接涉及 ShouldSkip
节点作为第二个节点的路径。
同样,这假设您只对起始节点之后的直接节点没有设置
ShouldSkip
属性的路径感兴趣。