1

I'm working with ArangoDB and have a graph traversal scenario where I need to skip a specific node based on a property, but still infer an indirect connection (edge) between two other nodes. My graph contains edges from A to B and B to C, but not directly from A to C. Node B has a property `ShouldSkip` set to true, and I want to skip it in the traversal results.

The desired outcome is to get edges: edge from A to C (inferred), and nodes: A and C, effectively skipping B in the results. However, since there's no direct edge from A to C in the graph, I'm not sure how to represent this in the query results.

Here's my current AQL query:

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))}

How can I adjust this query to infer an edge from A to C (only! without A to B and B to C), or is there a better approach to achieve this in ArangoDB (like while in indexing create a virtual edge of A to C - much less preferable)?

enter image description here

Effectively I would like the response to be: nodes: [A,C] edges: [{_from: A, _to: C}]

1 Answer 1

1

Another solution,

  1. Find all paths.
  2. Prepare a filtered nodes array by the property
  3. Inferre a run-time edges according to the filtered nodes array.
  4. Return them all distinct.

Full code:

// Define the starting node ID and the depth for the graph traversal
LET startNodeId = @startNode
LET depth = @depth
// Retrieve the document (node) corresponding to the startNodeId from the specified collection
LET startNode = DOCUMENT(@nodeCollectionName, startNodeId)

// Step 1: Find all paths from the start node up to the specified depth in the graph
LET allPaths = (
    FOR v, e, p IN 1..depth ANY startNode GRAPH @graphName
    // Return each path found during the traversal
    RETURN p
)

// Step 2: Filter the paths' nodes based on the 'ShouldSkip' property
LET filteredPaths = (
    FOR path IN allPaths
    // Filter out vertices in each path where 'ShouldSkip' is false
    LET filteredVertices = (FOR vertex IN path.vertices FILTER vertex.ShouldSkip == false RETURN vertex)
    // Return the filtered vertices along with the original path
    RETURN {{vertices: filteredVertices, originalPath: path }}
)

// Step 3: Infer the edges of the filtered nodes paths
LET inferredEdges = FLATTEN(
    FOR filteredPath IN filteredPaths
    // Create new edges between consecutive visible vertices
    LET edges = (
        FOR i IN 0..LENGTH(filteredPath.vertices) - 2
        LET startVertex = filteredPath.vertices[i]
        LET endVertex = filteredPath.vertices[i + 1]
        // Return a new edge from startVertex to endVertex
        RETURN {{_from: startVertex._id, _to: endVertex._id }}
    )
    // Flatten the list of edges for all paths
    RETURN edges
)

// Deduplicate the inferred edges
LET distinctEdges = UNIQUE(inferredEdges)

// Extract and deduplicate nodes from the filtered paths
LET allNodes = FLATTEN(
    FOR path IN filteredPaths
    // Extract vertices from each filtered path
    RETURN path.vertices
)
// Deduplicate the nodes
LET distinctNodes = UNIQUE(allNodes)

// Return the start node, distinct nodes, and distinct edges
RETURN 
{{
    StartNode: startNode,
    Nodes: distinctNodes,
    Edges: distinctEdges
}}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.