> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cyborg.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Query Metadata

Finds items by metadata alone, with no query vector. `query_metadata()` resolves the filter against the encrypted metadata index and returns the matching IDs. With `text`, it also ranks matches by BM25 relevance. It works on untrained indexes.

```python theme={null}
index.query_metadata(
    filters=None,
    top_k=None,
    order_by=None,
    ascending=True,
    text=None,
    text_fields=None,
    text_field_weights=None,
    require_all_terms=None,
) -> List[MetadataResult]
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `filters` | `Dict[str, Any]` | `None` | *(Optional)* Metadata filter; `None` or `{}` matches everything. See [Filter constraints](#filter-constraints). |
| `top_k` | `int` | `None` | *(Optional)* Maximum results; `None` returns every match. Applied after `order_by`. |
| `order_by` | `str` or `Dict[str, int]` | `None` | *(Optional)* Sort by a metadata field: a field name (direction set by `ascending`), or a single-field dict such as `{"views": -1}` for descending. Can't be combined with `text`. |
| `ascending` | `bool` | `True` | *(Optional)* Sort direction when `order_by` is a field name. Ignored when `order_by` is a dict. |
| `text` | `str` | `None` | *(Optional)* Query text for BM25 full-text ranking. Requires an index with at least one full-text field. Results then carry a `score`, sorted by relevance, and `filters` act as a pre-filter. |
| `text_fields` | `List[str]` | `None` (all full-text fields) | *(Optional)* Full-text fields to search. |
| `text_field_weights` | `List[float]` | `None` (`1.0` each) | *(Optional)* Weight per searched field, in the same order as `text_fields`. |
| `require_all_terms` | `bool` | `None` (service default: `False`) | *(Optional)* Match only items containing every query term. |

<Note>
  * Without `order_by` or `text`, results come back in no particular order.
  * Items missing the `order_by` field, or holding a non-scalar value in it, sort last.
</Note>

### Filter constraints

[`query()`](./query) falls back to a post-filter over decrypted metadata when the index can't answer a filter, for pure vector queries. `query_metadata()` has no fallback, so every filter must be answerable from the index. The index's [`metadata_schema`](../client/create-index#metadata-schema) is therefore enforced here:

* `$regex` and `$contains` need a field created with `pattern: True`.
* A field created with `filterable: False` can't be filtered on.
* `$type` isn't supported.

Any of these returns `cyborgdb.ValidationError` (HTTP `400`) with the reason. Nested dot-paths such as `"loc.city"` are supported.

### Returns

`List[MetadataResult]`: one dict per match.

```python theme={null}
{
    "id": str,     # Always returned
    "score": float, # Only when text is set. BM25 relevance; higher is more relevant.
}
```

### Exceptions

<AccordionGroup>
  <Accordion title="cyborgdb.ValidationError">
    `order_by` is a dict with more than one key, or is neither a `str` nor a dict (raised before any request is sent), or the service rejects the query (HTTP `400`): see [Filter constraints](#filter-constraints).
  </Accordion>

  <Accordion title="cyborgdb.AuthenticationError">
    The `index_key` or `api_key` is invalid (HTTP `401`).
  </Accordion>

  <Accordion title="cyborgdb.ServiceError / cyborgdb.TransportError">
    The service returns `5xx` or can't be reached.
  </Accordion>
</AccordionGroup>

See [Errors](../errors) for the full hierarchy.

### Example Usage

#### Filter only

```python theme={null}
results = index.query_metadata(filters={"label": "dog"})
print(sorted(r["id"] for r in results))  # unordered without order_by
# Output: ['101', '102']
```

#### Operators and a result cap

```python theme={null}
results = index.query_metadata(
    filters={"$and": [{"label": "cat"}, {"confidence": {"$gte": 0.9}}]},
    top_k=10,
)
print(results)
# Output: [{'id': '201'}]
```

#### Sorted by a field

```python theme={null}
# Ascending by "views"
results = index.query_metadata(filters={"label": "dog"}, order_by="views")

# Descending by "views"; top_k applies after the sort
results = index.query_metadata(
    filters={"label": "dog"},
    order_by={"views": -1},
    top_k=5,
)
print([r["id"] for r in results])
# Output: ['102', '101']
```

#### Regex match

```python theme={null}
# "title" must have been created with pattern=True
results = index.query_metadata(filters={"title": {"$regex": "^intro"}})
```

#### Full-text search

```python theme={null}
# The index needs a full-text field, e.g. create_index(..., text_fields=["body"])
results = index.query_metadata(text="encrypted search", top_k=5)

for r in results:
    print(r["id"], round(r["score"], 4))
```

For filter syntax and operators, see [Metadata filtering](../types#metadata-filtering).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.