Typesense Integration for Website Search
Typesense — open-source search engine written in C++. Positioned as cloud alternative to Algolia with self-hosted deployment. Response time consistently under 50ms on millions of documents. Supports vector search via HNSW, semantic search via embeddings, and classic full-text search.
Differences from Meilisearch
| Feature | Typesense | Meilisearch |
|---|---|---|
| Language | C++ | Rust |
| Clustering | Built-in (Raft) | Missing in OSS |
| Vector search | Yes (HNSW) | Yes (v1.6+) |
| Geo-search | Native | Yes |
| Query analytics | Built-in | Via third-party |
| Strict schema | Required | Optional |
Installation
# docker-compose.yml
services:
typesense:
image: typesense/typesense:0.25.2
command: >
--data-dir /data
--api-key=${TYPESENSE_API_KEY}
--listen-port=8108
--enable-cors
volumes:
- typesense_data:/data
ports:
- "8108:8108"
Collection Schema
Typesense uses strict schema. Define before adding documents:
{
"name": "products",
"fields": [
{ "name": "id", "type": "string" },
{ "name": "name", "type": "string" },
{ "name": "description", "type": "string" },
{ "name": "price", "type": "float", "facet": true },
{ "name": "category", "type": "string", "facet": true },
{ "name": "brand", "type": "string", "facet": true },
{ "name": "in_stock", "type": "bool", "facet": true },
{ "name": "rating", "type": "float", "optional": true },
{ "name": "location", "type": "geopoint","optional": true }
],
"default_sorting_field": "rating"
}
PHP Integration
composer require php-http/guzzle7-adapter typesense/typesense-php
use Typesense\Client;
$client = new Client([
'api_key' => env('TYPESENSE_API_KEY'),
'nodes' => [['host' => 'localhost', 'port' => '8108', 'protocol' => 'http']],
'connection_timeout_seconds' => 2,
]);
// Upsert document
$client->collections['products']->documents->upsert([
'id' => (string) $product->id,
'name' => $product->name,
'description' => strip_tags($product->description),
'price' => (float) $product->price,
'category' => $product->category->slug,
'brand' => $product->brand->name,
'in_stock' => $product->stock > 0,
'rating' => (float) $product->rating,
]);
Search with Facets
$results = $client->collections['products']->documents->search([
'q' => $query,
'query_by' => 'name,description,brand',
'query_by_weights' => '3,1,2',
'filter_by' => 'in_stock:true && price:[100..5000]',
'facet_by' => 'category,brand,price',
'max_facet_values' => 20,
'sort_by' => 'rating:desc',
'per_page' => 20,
'page' => 1,
]);
// $results['facet_counts'] — aggregations for filter display
Vector Search
Typesense accepts embedding vectors for semantic search. Model generation on application side:
// Index with vector (OpenAI text-embedding-3-small, dim=1536)
$client->collections['products']->documents->upsert([
'id' => '123',
'name' => 'Dell XPS 15 Laptop',
'embedding' => $vector, // float[]
]);
// Hybrid search: text + vector
$results = $client->collections['products']->documents->search([
'q' => 'powerful laptop for work',
'query_by' => 'name,embedding',
'vector_query' => 'embedding:([], k:10)',
]);
Geo-Search
Field geopoint accepts [lat, lng]. Radius search:
$results = $client->collections['stores']->documents->search([
'q' => '*',
'query_by' => 'name',
'filter_by' => 'location:(55.7558, 37.6173, 10 km)',
'sort_by' => 'location(55.7558, 37.6173):asc',
]);
Query Analytics
Typesense records search statistics: top queries, zero-result queries. Useful for SEO analysis and synonym tuning.
Work Timelines
| Stage | Time |
|---|---|
| Deployment, collection schema | 1 day |
| Indexer + sync | 2 days |
| Frontend search with facets | 2–3 days |
| Vector search (optional) | 2 days additional |
| Tests, relevance | 1 day |
Standard integration without vector search — 6–7 working days.







