Skip to content

POST /multihop/

Executes a multi-hop query across a namespace, applying a sequence of field-level filters to progressively narrow down candidates before returning the top results.


Request

Content-Type: application/json

Parameter Type Required Default Description
query object Key-value pairs representing the initial filter conditions
path array of [field, value] Ordered list of hops. Each hop is a [field, value] tuple applied sequentially to filter candidates
db_name string "fractal_db" Name of the database to query
namespace string "string" Namespace to query within the database
top_k int 10 Maximum number of results to return

Behavior

Multi-hop filtering — The query is executed in steps. The initial query dict filters the full candidate pool, then each entry in path applies an additional field-level filter to the surviving candidates. This allows traversal of structured relationships (e.g. filter by department, then by role, then by seniority).

Scoring — Each result is returned with a relevance score. Non-finite scores (NaN, Inf) are returned as null.

Data retrieval — Row metadata is fetched directly from RocksDB using the matched row IDs, so no CSV or in-memory DataFrame is required at query time.

Explanation — Every response includes a full trace of how many candidates survived each hop, making it easy to debug filter chains.


Responses

200 OK

{
  "results": [
    {
      "row_id": 42,
      "score": 0.91,
      "name": "Alice Johnson",
      "department": "Engineering",
      "role": "Senior Engineer"
    }
  ],
  "explanation": {
    "initial_filters_matched": 120,
    "final_result_count": 3,
    "hops": [
      {
        "field": "department",
        "value": "Engineering",
        "filter_type": "exact",
        "candidates_before": 120,
        "candidates_after": 40
      },
      {
        "field": "role",
        "value": "Senior Engineer",
        "filter_type": "exact",
        "candidates_before": 40,
        "candidates_after": 3
      }
    ],
    "trace": "..."
  },
  "db_name": "my_db",
  "namespace": "default",
  "top_k": 10,
  "query": {"department": "Engineering"},
  "path": [["role", "Senior Engineer"]]
}

results array — each item contains:

Field Description
row_id Internal row identifier
score Relevance score, or null if non-finite
... All other metadata fields stored for that row

explanation object:

Field Description
initial_filters_matched Candidates matched by the initial query
final_result_count Candidates remaining after all hops
hops Per-hop breakdown: field, value, filter type, and candidate counts before/after
trace Full internal trace string for debugging

Error Responses

Status Condition
500 Database not found, namespace not loaded, or unexpected internal error

Notes

  • The path order matters — hops are applied sequentially and each one filters the output of the previous.
  • Ensure the namespace is already ingested via /build_ingest_data/ before querying.
  • db_name and namespace must exactly match what was used during ingest.

Example

import requests

SERVER_URL = "http://hbserver:8000"
API_KEY    = "yourapitoken"

def multihop_query(query: dict, path: list, namespace: str) -> dict:
    response = requests.post(
        f"{SERVER_URL}/multihop/",
        headers={"X-API-Key": API_KEY},
        json={
            "query":     query,
            "path":      path,
            "db_name":   "my_db",
            "namespace": namespace,
            "top_k":     10,
        },
    )
    response.raise_for_status()
    return response.json()


result = multihop_query(
    query={"department": "Engineering"},
    path=[
        ["role", "Senior Engineer"],
        ["location", "New York"],
    ],
    namespace="default",
)
print(result)

Expected output:

{
  "results": [
    {
      "row_id": 42,
      "score": 0.91,
      "name": "Alice Johnson",
      "department": "Engineering",
      "role": "Senior Engineer",
      "location": "New York"
    }
  ],
  "explanation": {
    "initial_filters_matched": 120,
    "final_result_count": 1,
    "hops": [
      {
        "field": "role",
        "value": "Senior Engineer",
        "filter_type": "exact",
        "candidates_before": 120,
        "candidates_after": 8
      },
      {
        "field": "location",
        "value": "New York",
        "filter_type": "exact",
        "candidates_before": 8,
        "candidates_after": 1
      }
    ],
    "trace": "..."
  },
  "db_name": "my_db",
  "namespace": "default",
  "top_k": 10,
  "query": {"department": "Engineering"},
  "path": [["role", "Senior Engineer"], ["location", "New York"]]
}