DEV Community

Cover image for Introducing Recursive Graph Traversal Queries in GenosDB
Esteban Fuster Pozzi
Esteban Fuster Pozzi

Posted on • Originally published at genosdb.com

Introducing Recursive Graph Traversal Queries in GenosDB

Graph databases promise relationship queries, but most P2P databases stop at key-value lookups. Traversing a graph β€” following edges recursively across multiple levels with filtering at each depth β€” requires a query engine that understands topology, not just data.

Developers wanted to move beyond fetching nodes by their properties. They needed to ask deep, meaningful questions of their data graph, like "find all descendants of the 'Perez' family" or "show me every file in this project folder and all its subfolders." This is the essence of graph databases, and it presented a fascinating challenge.

The Challenge

For a P2P, decentralized database, every byte sent over the network matters. The most obvious way to enable relational queries would have been to "hydrate" our edges, embedding full node data within each link. This was a non-starter. It would have bloated network packets and destroyed the low-latency performance that is a core tenet of GenosDB.

Our design philosophy is non-negotiable: a node's edges array must remain a hyper-lightweight list of IDs.

So, the challenge was refined: How do we deliver powerful, multi-level graph exploration queries without adding a single byte to our network synchronization payload?

The answer was to make our query engine much smarter.

The $edge Operator

Today, we're thrilled to introduce the new $edge operator. It's an elegant, powerful addition to our query syntax that transforms a standard filter into a deep graph exploration.

When you use $edge, you are telling the query engine: "Use the initial part of my query to find the starting points, then, from there, begin a recursive traversal of all connected nodes, returning a final list of all descendants that match my criteria."

This all happens at query time, leveraging the in-memory graph to follow the lightweight ID references. The result is a true graph query experience with the performance of a decentralized P2P network.

Try it live in the GenosDB Ultimate Sandbox

Basic Usage

Let's see it in action. Imagine you want to find all members of the "Perez" family, including children, grandchildren, and so on.

// Find all descendants of the "Perez" family who are of type 'Person'
const { results } = await db.map({
  query: {
    // 1. First, find our starting point(s)
    type: 'Family',
    name: 'Perez',

    // 2. Then, begin the graph traversal
    "$edge": {
      // 3. This filter is applied to EVERY descendant found
      type: 'Person'
    }
  }
});

// The `results` array will contain a flat list of all people in the
// Perez family tree: Juan, Maria, Pedro, etc.
Enter fullscreen mode Exit fullscreen mode

Let's break this down:

  1. The query first finds all nodes matching { type: 'Family', name: 'Perez' }. These are our starting gates.
  2. The $edge operator then activates "graph mode". It begins an exhaustive search, following every edge from the starting gates, and every subsequent edge thereafter.
  3. The sub-query { type: 'Person' } acts as a filter. As the engine traverses the graph, it checks every node it encounters. If a node matches this filter, it's added to the final result set.

The result is not a "verification"; it's a consultation β€” a complete list of all the data you asked for.

Advanced Filtering

The sub-query inside $edge can use the full power of the GenosDB query language. You can use $and, $or, $gt, and all other operators to create highly specific explorations.

Let's find all files inside the "Projects" folder (and all its subfolders) that are either PDFs or images larger than 2MB.

// Find all matching files within a directory structure
const { results } = await db.map({
  query: {
    type: 'Folder',
    name: 'Projects'
  },
  "$edge": {
    $or: [
      { type: 'File', extension: 'pdf' },
      { type: 'File', extension: 'jpg', size_mb: { $gt: 2 } }
    ]
  }
});
Enter fullscreen mode Exit fullscreen mode

This single query can traverse a complex directory tree and pluck out exactly the files you need, no matter how deeply nested they are.

Stress Test: 50 Levels Deep

We knew this feature had to be rock-solid. To prove it, we designed a stress test: a graph with a linear chain of 51 nodes. We then wrote a query that required the engine to traverse all 50 links to find a target at the very end.

The result? Instantaneous.

The query engine resolved the entire 50-level deep path in milliseconds, proving that the recursive implementation is not only correct but also highly efficient and free from common issues like stack overflows.

What This Enables

By listening to our community, we were pushed to solve a difficult problem in a way that honors our commitment to performance and minimalism. The $edge operator is more than just a new feature; it's a testament to our philosophy of building powerful tools that deliver on their promise.

It transforms a key user concern into one of GenosDB's most powerful and defining features.

We invite you to explore the new recursive graph traversal capabilities and see what you can build.


This article is part of the official documentation of GenosDB (GDB).
GenosDB is a distributed, modular, peer-to-peer graph database built with a Zero-Trust Security Model, created by Esteban Fuster Pozzi (estebanrfp).

πŸ“„ Whitepaper | overview of GenosDB design and architecture

πŸ›  Roadmap | planned features and future updates

πŸ’‘ Examples | code snippets and usage demos

πŸ“– Documentation | full reference guide

πŸ” API Reference | detailed API methods

πŸ“š Wiki | additional notes and guides

πŸ’¬ GitHub Discussions | community questions and feedback

πŸ—‚ Repository | Minified production-ready files

πŸ“¦ Install via npm | quick setup instructions

🌐 Website | GitHub | LinkedIn

Top comments (0)