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
pathorder 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_nameandnamespacemust 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"]]
}