AACsearch
Migration Guides

Migrating from Typesense

Step-by-step guide for moving from Typesense to AACsearch Engine — migrate indexes, API keys, and search widgets.

Migrating from Typesense

This guide walks you through moving from Typesense to AACsearch Engine. The process is designed for minimal downtime and usually takes just a few hours.

Migration overview

StepWhat you doTime
1Export the index from Typesense~5 minutes
2Create the index in AACsearch~5 minutes
3Import the data~10 minutes
4Configure filters and synonyms~15 minutes
5Update API keys~10 minutes
6Update the frontend~30 minutes
7Switch to the new endpoint~5 minutes

Step 1: Export the index from Typesense

Use the Typesense CLI or API:

# Export documents to JSON
curl "http://localhost:8108/collections/products/documents/export" \
  -H "X-TYPESENSE-API-KEY: your_api_key" \
  > typesense-export.json

Or use the Typesense Python client:

import typesense
import json

client = typesense.Client({
  'nodes': [{'host': 'localhost', 'port': '8108', 'protocol': 'http'}],
  'api_key': 'your_api_key',
  'connection_timeout_seconds': 2
})

collection = client.collections['products'].retrieve()
documents = client.collections['products'].documents.export()

with open('typesense-export.json', 'w') as f:
    f.write(documents)

Step 2: Create the index in AACsearch

In the AACsearch dashboard or via the API:

curl -X POST "https://app.aacsearch.com/api/v1/indexes" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "products",
    "fields": [
      {"name": "id", "type": "string", "indexing": true},
      {"name": "title", "type": "string", "indexing": true},
      {"name": "description", "type": "string", "indexing": true},
      {"name": "price", "type": "float", "sort": true},
      {"name": "category", "type": "string", "facet": true},
      {"name": "rating", "type": "float", "sort": true},
      {"name": "in_stock", "type": "bool", "facet": true}
    ]
  }'

Step 3: Import the data

Transform the exported data and upload it:

# Exported documents typically come in JSON Lines format.
# You can usually import them directly:
curl -X POST "https://app.aacsearch.com/api/v1/indexes/products/documents/batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d @typesense-export.json

Or transform into the expected format:

import json

# Read the exported documents
with open('typesense-export.json', 'r') as f:
    lines = f.readlines()
    documents = [json.loads(line) for line in lines]

# Make sure every document has an "id" field
for doc in documents:
    if 'id' not in doc:
        doc['id'] = str(doc.get('object_id', ''))  # or another unique identifier

# Save as JSON
with open('import-data.json', 'w') as f:
    json.dump(documents, f)

# Upload
import requests
with open('import-data.json', 'r') as f:
    response = requests.post(
        'https://app.aacsearch.com/api/v1/indexes/products/documents/batch',
        headers={'Authorization': 'Bearer YOUR_API_KEY'},
        json=json.load(f)
    )
    print(response.json())

Step 4: Configure search settings

Filters (facets)

Translate Typesense parameters:

TypesenseAACsearchNotes
facet_by: ["category"]"facet": true on the fieldFilterable field
group_by: ["brand"]String array "type": "string[]"Result grouping

Synonyms

Export synonyms from Typesense and import them into AACsearch:

# Export synonyms from Typesense
curl "http://localhost:8108/synonyms" \
  -H "X-TYPESENSE-API-KEY: your_api_key" \
  > typesense-synonyms.json

# Import into AACsearch
curl -X POST "https://app.aacsearch.com/api/v1/indexes/products/synonyms" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {"synonyms": ["sneakers", "trainers", "running shoes"]},
    {"synonyms": ["phone", "smartphone", "mobile"]},
    {"synonyms": ["laptop", "notebook", "computer"]}
  ]'

Relevance sorting

Typesense uses a textMatchScore * popularity formula. AACsearch ships built-in ranking strategies:

# Update ranking rules
curl -X PUT "https://app.aacsearch.com/api/v1/indexes/products/ranking" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sortByFields": [
      {"field": "relevance", "order": "desc"},
      {"field": "rating", "order": "desc"},
      {"field": "price", "order": "asc"}
    ]
  }'

Step 5: Update API keys

Create new API keys in AACsearch:

# Create a search key (public)
curl -X POST "https://app.aacsearch.com/api/v1/keys" \
  -H "Authorization: Bearer YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search API Key",
    "scope": "search",
    "indexes": ["products"]
  }'

# Result:
# {
#   "key": "ss_search_...",
#   "keyHash": "..."
# }

Important: the search key (public) is safe to embed in the client. Never use admin keys on the client.

Step 6: Update the frontend

JavaScript

// Old Typesense code
const typesense = new Typesense.SearchClient({
  nodes: [{
    host: 'localhost',
    port: 8108,
    protocol: 'http'
  }],
  apiKey: 'your_api_key',
  connectionTimeoutSeconds: 2
});

// New AACsearch code
const searchClient = new AACSearchClient({
  apiKey: 'ss_search_...',
  baseURL: 'https://app.aacsearch.com'
});

// Search
const results = await searchClient.search({
  indexSlug: 'products',
  query: 'sneakers',
  filters: { category: 'footwear', price: { lte: 10000 } },
  limit: 20
});

Python

import aac_search

client = aac_search.AACSearchClient(
    api_key='ss_search_...',
    base_url='https://app.aacsearch.com'
)

results = client.search(
    index_slug='products',
    query='sneakers',
    filters={'category': 'footwear', 'price': {'lte': 10000}},
    limit=20
)

for hit in results['hits']:
    print(hit['title'], hit['price'])

cURL

curl -X POST "https://app.aacsearch.com/api/v1/indexes/products/search" \
  -H "Authorization: Bearer ss_search_..." \
  -H "Content-Type: application/json" \
  -d '{
    "query": "sneakers",
    "filters": {"category": "footwear", "price": {"lte": 10000}},
    "limit": 20
  }'

Step 7: Switch to the new endpoint

Update the URL in your app

// Before
const searchURL = 'http://localhost:8108/collections/products/documents/search';

// After
const searchURL = 'https://app.aacsearch.com/api/v1/indexes/products/search';

Update the search widget

<!-- Old Typesense widget -->
<script src="https://cdn.jsdelivr.net/npm/typesense-instantsearch-adapter@2/dist/typesense-instantsearch-adapter.min.js"></script>

<!-- New AACsearch widget -->
<div id="aac-search"></div>
<script
  src="https://app.aacsearch.com/api/widget/widget.js"
  data-api-key="ss_search_..."
  data-index-slug="products"
  data-container="#aac-search">
</script>

Verifying the migration

  1. Document count: confirm all documents were loaded

    curl "https://app.aacsearch.com/api/v1/indexes/products" \
      -H "Authorization: Bearer YOUR_API_KEY"
  2. Search works: try a few searches

    curl -X POST "https://app.aacsearch.com/api/v1/indexes/products/search" \
      -H "Authorization: Bearer ss_search_..." \
      -d '{"query": "sneakers"}'
  3. Filters work: verify category and price filters

  4. Performance: compare the latency of the old and new search

Rolling back to Typesense

If you hit issues you can roll back to Typesense:

// Point the URL back to Typesense
const searchURL = 'http://localhost:8108/collections/products/documents/search';

// Clear the browser cache (Ctrl+Shift+Delete)

Frequently asked questions

Q: Did all documents load? A: Check the AACsearch dashboard → Search → Stats. The total should match Typesense.

Q: Why does search behave differently? A: AACsearch and Typesense use different ranking algorithms. That is expected. You can fine-tune sort order in index settings.

Q: Do I need to optimize anything? A: AACsearch optimizes indexes automatically. You don't need to do anything.

Q: How fast are new documents indexed? A: New documents are indexed within a few seconds.

Q: Does AACsearch support hierarchical filters? A: Yes, use string arrays for hierarchical filters (e.g., ["Women's footwear", "Sneakers"]).

Help and support

On this page