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

# Search

> Semantic search across one or more namespaces using a text or vector query.

## Overview

Search stored items by semantic similarity and return ranked results with scores and relevance labels.

* **Text query** — query string is embedded via your configured provider; search **text** namespaces
* **Vector query** — pass a numeric array; search **vector** namespaces (length must match each namespace's `vector_dimension`)

Text queries support **metadata** and **keyword** filters using `#key:value` and `#keyword` syntax at the end of the query (same as cloud Moorcheh).

<Note>
  Search errors return `"status": "error"` (not `"failure"`) with HTTP **400**.
</Note>

## Headers

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`
</ParamField>

## Body

<ParamField body="query" type="string | array" required>
  Text string or array of numbers. For text queries, include metadata and keyword filters using `#key:value` and `#keyword` syntax at the **end** of the query.
</ParamField>

<ParamField body="namespaces" type="array" required>
  Non-empty list of namespace names to search. Each namespace must exist and match the query type (text vs vector).
</ParamField>

<ParamField body="top_k" type="number" default="10">
  Maximum number of results to return. Clamped to **1–100**. Default is `10` if omitted.
</ParamField>

<ParamField body="threshold" type="number" default="0">
  Minimum score threshold (**0–1**). Used when `kiosk_mode` is `true`.
</ParamField>

<ParamField body="kiosk_mode" type="boolean" default="false">
  When `true`, `threshold` is **required** and results below the threshold are filtered out.
</ParamField>

## Advanced filtering

### Metadata filters

Use `#key:value` at the end of the query to filter by stored metadata:

* `#department:engineering` — items where `department` equals `engineering` (case-insensitive)
* `#category:tech` — items where `category` equals `tech`

### Keyword filters

Use `#keyword` (no colon) to require that word in the result text:

* `#important` — result text must contain `important`
* `#python` — result text must contain `python`

### Combined example

```
authentication #category:security #important
```

Embeds `authentication`, filters metadata `category=security`, then keeps only hits whose text contains `important`.

<Warning>
  * Filters must be placed at the **end** of your query
  * Use hyphens instead of spaces in filter values (e.g. `#author:john-doe`)
  * Vector queries do not support `#` filters (text queries only)
</Warning>

<RequestExample>
  ```bash Text search theme={null}
  curl -X POST "http://localhost:8080/search" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "on prem retrieval",
      "namespaces": ["my-documents"],
      "top_k": 5
    }'
  ```

  ```bash Search with metadata filter theme={null}
  curl -X POST "http://localhost:8080/search" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "product documentation #department:engineering",
      "namespaces": ["my-documents"],
      "top_k": 5
    }'
  ```

  ```bash Combined metadata + keyword filters theme={null}
  curl -X POST "http://localhost:8080/search" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "machine learning #department:engineering #semantic",
      "namespaces": ["my-documents"],
      "top_k": 10,
      "kiosk_mode": true,
      "threshold": 0.15
    }'
  ```

  ```bash Vector search theme={null}
  curl -X POST "http://localhost:8080/search" \
    -H "Content-Type: application/json" \
    -d '{
      "query": [0.1, 0.2, 0.3, 0.4, 0.5],
      "namespaces": ["my-embeddings"],
      "top_k": 5
    }'
  ```
</RequestExample>

<Note>
  For vector search, the `query` array length must match `vector_dimension` for each namespace (for example `5` or `768` depending on how the namespace was created).
</Note>

## Response fields

<ResponseField name="results" type="array">
  Ranked search hits, highest score first. Empty array when nothing matches (including strict metadata or keyword filters).
</ResponseField>

<ResponseField name="results[].id" type="string">
  Item id in the namespace (for file upload: `{file_id}_chunk_{n}` or `{file_id}_summary_{batch}`).
</ResponseField>

<ResponseField name="results[].namespace" type="string">
  Namespace that owns this result.
</ResponseField>

<ResponseField name="results[].score" type="number">
  Similarity score between **0** and **1**, rounded to 6 decimal places.
</ResponseField>

<ResponseField name="results[].label" type="string">
  Human-readable relevance label derived from the score (see table below).
</ResponseField>

<ResponseField name="results[].metadata" type="object">
  Metadata stored with the item. For the top relevant **content** chunk, may include `summary_chunk_id` (bare id) and `summary_text` (batch summary fetched automatically). Uploaded file chunks also include `file_id`, `filename`, `source`, etc.
</ResponseField>

<ResponseField name="results[].text" type="string">
  Document text for **text** namespace hits. Empty string `""` for **vector** namespace hits.
</ResponseField>

<ResponseField name="execution_time" type="number">
  Total request time in seconds.
</ResponseField>

<ResponseField name="timings" type="object">
  Detailed timing breakdown for each search phase, in seconds.
</ResponseField>

<ResponseField name="status" type="string">
  `"error"` on validation or search failures (HTTP 400).
</ResponseField>

<ResponseField name="message" type="string">
  Error description when the request fails.
</ResponseField>

<ResponseExample>
  ```json 200 - Text search theme={null}
  {
    "results": [
      {
        "id": "a1b2c3d4e5f67890_chunk_0",
        "namespace": "my-documents",
        "score": 0.566222,
        "label": "High Relevance",
        "metadata": {
          "file_id": "a1b2c3d4e5f67890",
          "filename": "document.pdf",
          "department": "engineering",
          "summary_chunk_id": "a1b2c3d4e5f67890_summary_0",
          "summary_text": "This batch summary covers the main topics in document.pdf..."
        },
        "text": "Sample document content about product features and architecture..."
      }
    ],
    "execution_time": 0.108234,
    "timings": {
      "parse_validate": 0.0,
      "prepare_vector": 0.107252,
      "fetch_data": 0.0,
      "calculate_distance": 0.000336,
      "select_candidates": 0.0,
      "calculate_scores": 0.000072,
      "reorder": 0.0,
      "format_response": 0.0,
      "total": 0.108234
    }
  }
  ```

  ```json 200 - No matches theme={null}
  {
    "results": [],
    "execution_time": 0.040776,
    "timings": {
      "parse_validate": 0.0,
      "prepare_vector": 0.040736,
      "fetch_data": 0.0,
      "calculate_distance": 0.000033,
      "select_candidates": 0.0,
      "calculate_scores": 0.0,
      "reorder": 0.0,
      "format_response": 0.0,
      "total": 0.040776
    }
  }
  ```

  ```json 400 - Empty query theme={null}
  {
    "status": "error",
    "message": "query is required"
  }
  ```
</ResponseExample>

## Relevance labels

| Score range | Label               |
| ----------- | ------------------- |
| ≥ 0.894     | Close Match         |
| ≥ 0.632     | Very High Relevance |
| ≥ 0.447     | High Relevance      |
| ≥ 0.316     | Good Relevance      |
| ≥ 0.224     | Low Relevance       |
| ≥ 0.1       | Very Low Relevance  |
| \< 0.1      | Irrelevant          |

## Summary enrichment

For the **top search hit** (or the second hit when the first is a summary chunk), the API fetches the linked batch summary and adds `summary_text` to that result's metadata. Only one result per search is enriched. `/answer` uses the same behavior for RAG context.

## Important notes

<Warning>
  * Text search requires your configured embedding provider (Ollama, OpenAI, or Cohere)
  * You cannot search text namespaces with a vector query or vice versa
  * `#key:value` metadata filters are case-insensitive; keyword filters match substrings in result text
  * With `kiosk_mode: true`, set `threshold` (0–1) to control minimum relevance
</Warning>

## Related

* [Upload file](/on-prem/api-references/files/upload)
* [CLI: moorcheh search](/on-prem/cli/search/query)
* [Python: similarity\_search.query()](/on-prem/python-client/search/query)
