> ## 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. `queryMetadata()` 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.

```typescript theme={null}
async queryMetadata({
    filters?: FilterExpression,
    topK?: number,
    orderBy?: string | { [field: string]: number },
    ascending?: boolean,
    text?: string,
    textFields?: string[],
    textFieldWeights?: number[],
    requireAllTerms?: boolean,
} = {}): Promise<MetadataResult[]>
```

### Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `filters` | `FilterExpression` | `{}` | *(Optional)* Metadata filter; omitted or `{}` matches everything. See [Filter constraints](#filter-constraints). |
| `topK` | `number` | `undefined` | *(Optional)* Maximum results; omit to return every match. Applied after `orderBy`. |
| `orderBy` | `string` or `{ [field]: number }` | `undefined` | *(Optional)* Sort by a metadata field: a field name (direction set by `ascending`), or a single-field object such as `{ views: -1 }` for descending. Can't be combined with `text`. |
| `ascending` | `boolean` | `true` | *(Optional)* Sort direction when `orderBy` is a field name. Ignored when `orderBy` is an object. |
| `text` | `string` | `undefined` | *(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. |
| `textFields` | `string[]` | `undefined` (all full-text fields) | *(Optional)* Full-text fields to search. |
| `textFieldWeights` | `number[]` | `undefined` (`1.0` each) | *(Optional)* Weight per searched field, in the same order as `textFields`. |
| `requireAllTerms` | `boolean` | `undefined` (service default: `false`) | *(Optional)* Match only items containing every query term. |

<Note>
  * Without `orderBy` or `text`, results come back in no particular order.
  * Items missing the `orderBy` 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. `queryMetadata()` has no fallback, so every filter must be answerable from the index. The index's [`metadataSchema`](../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 throws `CyborgDBValidationError` (HTTP `400`) with the reason. Nested dot-paths such as `'loc.city'` are supported.

### Returns

`Promise<MetadataResult[]>`: one object per match.

```typescript theme={null}
{
    id: string,     // Always returned
    score?: number, // Only when text is set. BM25 relevance; higher is more relevant.
}
```

### Exceptions

<AccordionGroup>
  <Accordion title="CyborgDBValidationError">
    * `orderBy` is an object with more than one key, or isn't a string or object. Thrown before any request is sent.
    * The service rejects the query (HTTP `400`): see [Filter constraints](#filter-constraints).
  </Accordion>

  <Accordion title="CyborgDBAuthenticationError">
    The `indexKey` or `apiKey` is invalid (HTTP `401`).
  </Accordion>

  <Accordion title="CyborgDBServiceError">
    The service returns `5xx`.
  </Accordion>
</AccordionGroup>

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

### Example Usage

#### Filter only

```typescript theme={null}
const results = await index.queryMetadata({ filters: { label: 'dog' } });
console.log(results.map((r) => r.id).sort()); // unordered without orderBy
// Output: [ '101', '102' ]
```

#### Operators and a result cap

```typescript theme={null}
const results = await index.queryMetadata({
    filters: { $and: [{ label: 'cat' }, { confidence: { $gte: 0.9 } }] },
    topK: 10,
});
console.log(results);
// Output: [ { id: '201' } ]
```

#### Sorted by a field

```typescript theme={null}
// Ascending by "views"
const ascending = await index.queryMetadata({ filters: { label: 'dog' }, orderBy: 'views' });

// Descending by "views"; topK applies after the sort
const top = await index.queryMetadata({
    filters: { label: 'dog' },
    orderBy: { views: -1 },
    topK: 5,
});
console.log(top.map((r) => r.id));
// Output: [ '102', '101' ]
```

#### Regex match

```typescript theme={null}
// "title" must have been created with pattern: true
const results = await index.queryMetadata({ filters: { title: { $regex: '^intro' } } });
```

#### Full-text search

```typescript theme={null}
// The index needs a full-text field, e.g. createIndex({ ..., textFields: ['body'] })
const results = await index.queryMetadata({ text: 'encrypted search', topK: 5 });

for (const r of results) {
    console.log(r.id, Number(r.score?.toFixed(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.