Full-Text Search — MDDB API

Keyword-based full-text search

Full-text search #

POST /v1/fts

Perform full-text search across documents in a collection. Supports 7 search modes with auto-detection and multi-language stemming (18 languages).

Search modes (mode parameter, default auto):

  • simple: Classic keyword search scored by algorithm (TF-IDF, BM25, BM25F, PMISparse)
  • boolean: AND/OR/NOT operators, +required, -excluded terms
  • phrase: Exact word sequence matching using "quoted phrases"
  • wildcard: Pattern matching with * (any chars) and ? (single char)
  • proximity: Terms within N words — "term1 term2"~5
  • auto (default): Auto-detects mode from query syntax (quotes → phrase, operators → boolean, etc.)

Algorithms (for simple/boolean modes):

  • tfidf (default): Classic TF-IDF scoring
  • bm25: Okapi BM25 with document length normalization (k1=1.2, b=0.75)
  • bm25f: BM25F field-weighted scoring — applies different weights to title, metadata, and content fields
  • pmisparse: PMISparse — BM25 + PMI query expansion

Range filtering: Use rangeMeta to filter by numeric, date, or string ranges on metadata fields.

In-graph filtering: Use filterMeta to narrow results by metadata before scoring, same as vector search.

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: FTSSearchRequest

{
  "algorithm": "bm25",
  "bm25B": 0.75,
  "bm25K1": 0,
  "boost": {
    "category:health": -2,
    "tag:breed": 5
  },
  "cacheTtl": 60,
  "collection": "blog",
  "disableStem": false,
  "disableSynonyms": false,
  "distance": 5,
  "facetBy": [
    "category",
    "lang"
  ],
  "facetMaxValues": 0,
  "facetScope": "returned",
  "fieldWeights": {
    "content": 1,
    "meta": 2,
    "title": 3
  },
  "filter": {
    "kind": {
      "not": [
        "test"
      ]
    },
    "modified": {
      "gte": "2026-09-01"
    },
    "path": {
      "prefix": "internal/"
    },
    "size": {
      "lt": 10000
    },
    "summary": {
      "exists": true
    },
    "title": {
      "contains": "hnsw"
    }
  },
  "filterMeta": {
    "category": [
      "tutorial"
    ]
  },
  "format": "results",
  "fragmentSize": 150,
  "fuzzy": 0,
  "groupBy": {
    "key": "path",
    "perGroup": 1
  },
  "highlight": false,
  "highlightTag": "\u003cmark\u003e",
  "includeImages": false,
  "lang": "en",
  "limit": 50,
  "maxHighlights": 3,
  "mode": "auto",
  "passageLines": 0,
  "query": "cancel subscription",
  "rangeMeta": [
    {
      "field": "price",
      "gt": "string",
      "gte": "10",
      "lt": "string",
      "lte": "100"
    }
  ]
}

Responses #

Status Description Body
200 Full-text search results oneOf FTSSearchResponse | PassagesResponse (application/json)
400 Invalid request ErrorResponse (application/json)

Reindex FTS for a collection #

POST /v1/fts-reindex

Re-indexes all documents in a collection using their stored lang field for language-aware stemming and stop words. Use this after enabling multi-language support to update existing documents indexed with the default English pipeline. Every document is rebuilt from scratch, unlike a write, which since v2.18.10 re-indexes only what changed (#367): run it after changing stop words, stemming or the collection's fts.excludeMetaKeys.

Authorization: BearerAuth or APIKeyAuth or none

Request body #

Required.

Content type application/json: object

Property Type Description
collection (required) string Collection name to reindex
{
  "collection": "string"
}

Responses #

Status Description Body
200 Reindex completed object (application/json)
500 The documents could not be read
400 Body is not JSON, or collection is missing ErrorResponse (application/json)

Prefix autocomplete #

GET /v1/autocomplete

Return up to topN terms starting with the given query, ranked by document frequency. Uses the existing FTS inverted index — no additional indexing is required.

When field is supplied, the BM25F field-scoped index drives the scan so callers can autocomplete titles, tags, or body content independently. A single call scans at most 10000 index entries to keep latency bounded on pathological prefixes like "a".

Authorization: BearerAuth or APIKeyAuth or none

Parameters #

Name In Type Description
collection (required) query string Collection name
q (required) query string Prefix query — lowercased and stripped of non-alphanumerics
field query string Optional field scope (e.g. title, content, meta.tags); empty means global
topN query integer Maximum number of suggestions returned, never above MDDB_SEARCH_MAX_LIMIT or the collection's retrieval.maxTopK (v2.18.10+). Default 10.

Responses #

Status Description Body
200 Suggestions object (application/json)
400 The request is malformed (a body that is not JSON, a missing or invalid field, an unreadable body) or names a subsystem that is not initialized. The message says which. ErrorResponse (application/json)
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
403 The caller lacks the permission the route needs (SEC-019 access gate, auth on: read, write or admin on the collections the request names), or a write meets read-only mode (MDDB_MODE=read or the protocol's own mode). ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)

400 example (application/json)

{
  "error": "missing collection"
}

401 example (application/json)

{
  "error": "missing authentication"
}

403 example (application/json)

{
  "error": "forbidden"
}

List supported FTS languages #

GET /v1/fts-languages

Returns all supported languages for multi-language FTS with their codes, names, and the configured default language.

Authorization: BearerAuth or APIKeyAuth or none

Responses #

Status Description Body
200 Supported languages object (application/json)
401 Auth is on (MDDB_AUTH_ENABLED=true) and the request carries no credentials, an invalid or expired JWT, or an unknown API key. ErrorResponse (application/json)
429 The client is over the API rate limit (MDDB_RATE_LIMIT_ENABLED=true, MDDB_RATE_LIMIT_REQUESTS per MDDB_RATE_LIMIT_WINDOW seconds). A call that embeds can also be refused by the collection's daily embedding budget, with a QuotaExceeded body. RateLimitError (application/json)

401 example (application/json)

{
  "error": "missing authentication"
}