← All lessons/Indexes & Performance
20
Indexes & Performance

Full-Text Search

Index text fields for keyword search and use the fts operator.

Prerequisite: Lesson 18 complete

What you'll learn

  • POST /v1/agents/:id/indexes with type: 'fts'
  • Tokenizer: split on [^a-zA-Z0-9], lowercase, drop tokens < 2 chars
  • Inverted posting list stored as graph meta keys
  • Query: filter {field, op: 'fts', value: 'search terms'}
  • Multi-word FTS — AND semantics across all query words
  • FTS inside compound filters
Challenge

Create notes agent with FTS index on body. Write 10 notes with varied text. Search for a word in some but not all.

Interactive Walkthrough

What you'll learn

Index text fields for keyword search and use the fts operator.

Create an FTS index

curl -s -X POST http://localhost:7475/v1/agents/articles/indexes \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "name":  "idx_fts_content",
    "field": "content",
    "type":  "fts"
  }' | python3 -m json.tool

Write some articles

curl -s -X POST http://localhost:7475/v1/agents/articles/write/batch \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "records": [
      {"payload": {"title": "Getting started with SapixDB", "content": "SapixDB is an agent-native append-only database with cryptographic signing"}},
      {"payload": {"title": "Time travel queries", "content": "Query the past state of any agent using as_of timestamp"}},
      {"payload": {"title": "HIPAA compliance", "content": "SapixDB includes HIPAA PHI encryption and audit trails out of the box"}}
    ]
  }' | python3 -m json.tool

FTS query

curl -s -X POST http://localhost:7475/v1/agents/articles/query \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "type": "scan",
    "limit": 10,
    "filter": {"field": "content", "op": "fts", "value": "cryptographic signing"}
  }' | python3 -m json.tool

How FTS works internally

  • Tokenizer splits on [^a-zA-Z0-9], lowercases, drops tokens shorter than 2 chars
  • Inverted posting list stored as graph meta keys: _fts:<index_name>:<word> → list of content_hashes
  • Query intersects posting lists for all query words (AND semantics)

FTS in compound filters

# Articles about HIPAA from 2026
curl -s -X POST http://localhost:7475/v1/agents/articles/query \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer spx_root_YOUR_ROOT_KEY" \
  -d '{
    "type": "scan",
    "limit": 10,
    "filter": {
      "AND": [
        {"field": "content", "op": "fts", "value": "HIPAA"},
        {"field": "year",    "op": "eq",  "value": 2026}
      ]
    }
  }' | python3 -m json.tool

Challenge

Create a notes agent with an FTS index on body. Write 10 notes with varied text. Search for a word that appears in some but not all. Confirm only matching records are returned.

---

← Previous
Lesson 19: Composite Indexes
Next →
Lesson 21: Query Explain