Welcome to the Typesense API documentation. This documentation itself is open source. Please leave your feedback as issues on the GitHub repo or send us a pull-request to contribute edits.
To learn how to install and run Typesense, see our getting started guide instead.
At the moment, we have API clients for Javascript, PHP, Python, and Ruby.
We recommend that you use our API client library if it is available for your language.
// Node.js
npm install typesense
// Browser
<script src="dist/typesense.min.js"></script>
composer require typesense/typesense-php
pip install typesense
gem install typesense
If you're using our Javascript client to access Typesense directly from the browser, be sure to start the
Typesense server with the --enable-cors
flag.
/*
* Our Javascript client library works on both the server and the browser.
* When using the library on the browser, please be sure to use the
* search-only API Key rather than the master API key since the latter
* has write access to Typesense and you don't want to expose that.
*/
let client = new Typesense.Client({
'nodes': [{
'host': 'localhost',
'port': '8108',
'protocol': 'http',
}],
'apiKey': '<API_KEY>'
'connectionTimeoutSeconds': 2
})
use Typesense\Client;
$client = new Client(
[
'nodes' => [
[
'host' => 'localhost',
'port' => '8108',
'protocol' => 'http',
],
],
'api_key' => '<API_KEY>',
'connection_timeout_seconds' => 2,
]
);
import typesense
client = typesense.Client({
'nodes': [{
'host': 'localhost',
'port': '8108',
'protocol': 'http',
}],
'api_key': '<API_KEY>',
'connection_timeout_seconds': 2
})
require 'typesense'
client = Typesense::Client.new(
nodes: [
{
host: 'localhost',
port: 8108,
protocol: 'http'
}
],
api_key: '<API_KEY>',
connection_timeout_seconds: 2
)
# API authentication is done via the `X-TYPESENSE-API-KEY` HTTP header.
curl -H "X-TYPESENSE-API-KEY: <API_KEY>" "http://localhost:8108/collections"
In Typesense, a group of related documents is called a collection
. A collection
is roughly
equivalent to a table in a relational database.
When a collection
is created, we give it a name and describe the fields that will be indexed
from the documents that are added to the collection
.
Your documents can contain other fields not mentioned in the collection's schema - they will be stored but not indexed.
let schema = {
'name': 'companies',
'num_documents': 0,
'fields': [
{
'name': 'company_name',
'type': 'string',
'facet': false
},
{
'name': 'num_employees',
'type': 'int32',
'facet': false
},
{
'name': 'country',
'type': 'string',
'facet': true
}
],
'default_sorting_field': 'num_employees'
}
client.collections().create(schema)
$schema = [
'name' => 'companies',
'fields' => [
[
'name' => 'company_name',
'type' => 'string'
],
[
'name' => 'num_employees',
'type' => 'int32'
],
[
'name' => 'country',
'type' => 'string',
'facet' => true
]
],
'default_sorting_field' => 'num_employees'
]
$client->collections->create($schema)
schema = {
'name': 'companies',
'fields': [
{
'name' : 'company_name',
'type' : 'string'
},
{
'name' : 'num_employees',
'type' : 'int32'
},
{
'name' : 'country',
'type' : 'string',
'facet' : True
}
],
'default_sorting_field': 'num_employees'
}
client.collections.create(schema)
schema = {
'name' => 'companies',
'fields' => [
{
'name' => 'company_name',
'type' => 'string'
},
{
'name' => 'num_employees',
'type' => 'int32'
},
{
'name' => 'country',
'type' => 'string',
'facet' => true
}
],
'default_sorting_field' => 'num_employees'
}
client.collections.create(schema)
curl "http://localhost:8108/collections" -X POST -H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -d '{
"name": "companies",
"fields": [
{"name": "company_name", "type": "string" },
{"name": "num_employees", "type": "int32" },
{"name": "country", "type": "string", "facet": true }
],
"default_sorting_field": "num_employees"
}'
{
"name": "companies",
"num_documents": 0,
"fields": [
{"name": "company_name", "type": "string" },
{"name": "num_employees", "type": "int32" },
{"name": "country", "type": "string", "facet": true }
],
"default_sorting_field": "num_employees"
}
POST ${TYPESENSE_HOST}/collections
Parameter | Required | Description |
---|---|---|
name | yes | Name of the collection you wish to create. |
fields | yes |
A list of fields that you wish to index for querying, filtering and faceting. For each field, you
have to specify the Declaring a field as optional A field can be declared as optional by setting Declaring a field as a facet A field can be declared as a facetable field by setting Faceted fields are indexed verbatim without any tokenization or preprocessing.
For example, if you are building a product search, |
default_sorting_field | yes |
The name of an Additionally, when a word in a search query matches multiple possible words (either because of a typo or during a prefix search), this parameter is used to rank such equally matching tokens. For e.g. both "john" and "joan" are 1-typo away from "jofn". Similarly, in a prefix search, both "apple" and "apply" would match the prefix "app". |
Typesense allows you to index the following types of fields:
string |
int32 |
int64 |
float |
bool |
You can define an array or multi-valued field by suffixing a []
at the end:
string[] |
int32[] |
int64[] |
float[] |
bool[] |
A document to be indexed in a given collection must conform to the schema of the collection.
If the document contains an id
field of type string
, Typesense would use that
field as the identifier for the document. Otherwise, Typesense would assign an identifier of its choice to
the document.
let document = {
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}
client.collections('companies').documents().create(document)
$document = [
'id' => '124',
'company_name' => 'Stark Industries',
'num_employees' => 5215,
'country' => 'USA'
]
$client->collections['companies']->documents->create($document)
document = {
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}
client.collections['companies'].documents.create(document)
document = {
'id' => '124',
'company_name' => 'Stark Industries',
'num_employees' => 5215,
'country' => 'USA'
}
client.collections['companies'].documents.create(document)
curl "http://localhost:8108/collections/companies/documents" -X POST \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}'
You can also upsert a document.
let document = {
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}
client.collections('companies').documents().upsert(document)
$document = [
'id' => '124',
'company_name' => 'Stark Industries',
'num_employees' => 5215,
'country' => 'USA'
]
$client->collections['companies']->documents->upsert($document)
document = {
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}
client.collections['companies'].documents.upsert(document)
document = {
'id' => '124',
'company_name' => 'Stark Industries',
'num_employees' => 5215,
'country' => 'USA'
}
client.collections['companies'].documents.upsert(document)
curl "http://localhost:8108/collections/companies/documents?action=upsert" -X POST \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}'
To index multiple documents at the same time, in a batch/bulk operation, see importing documents.
{
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}
POST ${TYPESENSE_HOST}/collections/:collection/documents
In Typesense, a search consists of a query against one or more text fields and a list of filters against numerical or facet fields. You can also sort and facet your results.
let searchParameters = {
'q' : 'stark',
'query_by' : 'company_name',
'filter_by' : 'num_employees:>100',
'sort_by' : 'num_employees:desc'
}
client.collections('companies').documents().search(searchParameters)
$searchParameters = [
'q' => 'stark',
'query_by' => 'company_name',
'filter_by' => 'num_employees:>100',
'sort_by' => 'num_employees:desc'
]
$client->collections['companies']->documents->search($searchParameters)
search_parameters = {
'q' : 'stark',
'query_by' : 'company_name',
'filter_by' : 'num_employees:>100',
'sort_by' : 'num_employees:desc'
}
client.collections['companies'].documents.search(search_parameters)
search_parameters = {
'q' => 'stark',
'query_by' => 'company_name',
'filter_by' => 'num_employees:>100',
'sort_by' => 'num_employees:desc'
}
client.collections['companies'].documents.search(search_parameters)
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/collections/companies/documents/search\
?q=stark&query_by=company_name&filter_by=num_employees:>100\
&sort_by=num_employees:desc"
{
"facet_counts": [],
"found": 1,
"out_of": 1,
"page": 1,
"request_params": { "q" : "" },
"search_time_ms": 1,
"hits": [
{
"highlights": [
{
"field": "company_name",
"snippet": "<mark>Stark</mark> Industries",
"matched_tokens": ["Stark"]
}
],
"document": {
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}
}
]
}
When a string[]
field is queried, the highlights
structure would include the
corresponding matching array indices of the snippets. For e.g:
{
...
"highlights": [
{
"field": "addresses",
"indices": [0,2],
"snippets": [
"10880 <mark>Malibu</mark> Point, <mark>Malibu,</mark> CA 90265",
"10000 <mark>Malibu</mark> Point, <mark>Malibu,</mark> CA 90265"
],
"matched_tokens": [
["Malibu", "Malibu"],
["Malibu", "Malibu"]
]
}
],
...
}
You can aggregate search results into groups or buckets by specify one or more group_by
fields.
Grouping hits this way is useful in:
group_by
fields, you can
consolidate items and remove duplicates in the search results. For example, if there are multiple
shoes of the same size, by doing a group_by=size&group_limit=1
, you ensure that only a
single shoe of each size is returned in the search results.group_by
and group_limit
to correct that skew.
For example, if your search results for a query contains way too many documents of the same brand
,
you can do a group_by=brand&group_limit=3
to ensure that only the top 3 results of each brand
is returned in the search results.NOTE: To group on a particular field, it must be a faceted field.
Grouping returns the hits in a nested structure, that's different from the plain JSON response format we saw
earlier. Let's repeat the query we made earlier with a group_by
parameter:
let searchParameters = {
'q' : 'stark',
'query_by' : 'company_name',
'filter_by' : 'num_employees:>100',
'sort_by' : 'num_employees:desc',
'group_by' : 'country',
'group_limit' : '1'
}
client.collections('companies').documents().search(searchParameters)
$searchParameters = [
'q' => 'stark',
'query_by' => 'company_name',
'filter_by' => 'num_employees:>100',
'sort_by' => 'num_employees:desc',
'group_by' => 'country',
'group_limit' => '1'
]
$client->collections['companies']->documents->search($searchParameters)
search_parameters = {
'q' : 'stark',
'query_by' : 'company_name',
'filter_by' : 'num_employees:>100',
'sort_by' : 'num_employees:desc',
'group_by' : 'country',
'group_limit' : '1'
}
client.collections['companies'].documents.search(search_parameters)
search_parameters = {
'q' => 'stark',
'query_by' => 'company_name',
'filter_by' => 'num_employees:>100',
'sort_by' => 'num_employees:desc',
'group_by' => 'country',
'group_limit' => '1'
}
client.collections['companies'].documents.search(search_parameters)
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/collections/companies/documents/search\
?q=stark&query_by=company_name&filter_by=num_employees:>100\
&sort_by=num_employees:desc&group_by=country&group_limit=1"
{
"facet_counts": [],
"found": 1,
"out_of": 1,
"page": 1,
"request_params": { "q" : "" },
"search_time_ms": 1,
"grouped_hits": [
{
"group_key": ["USA"],
"hits": [
{
"highlights": [
{
"field": "company_name",
"snippet": "<mark>Stark</mark> Industries"
}
],
"document": {
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}
}
]
}
]
}
GET ${TYPESENSE_HOST}/collections/:collection/documents/search
Parameter | Required | Description |
---|---|---|
q | yes |
The query text to search for in the collection.
Use For example, to return all documents that match a filter, use: |
query_by | yes |
One or more The order of the fields is important: a record that matches on a field earlier in the list is
considered more relevant than a record matched on a field later in the list.
So, in the example above, documents that match on the |
query_by_weights | no |
The relative weight to give each Separate each weight with a comma, in the same order as the |
max_hits | no | Maximum number of hits returned. Increasing this value might increase search latency. Use Default: |
prefix | no | Boolean field to indicate that the last word in the query should be treated as a prefix, and not as a whole word. This is necessary for building autocomplete and instant search interfaces. Default: |
filter_by | no | Filter conditions for refining your search results. A field can be matched against one or more values.
To match a string field exactly, you have to mark the field as a facet and use the
For example, Separate multiple conditions with the
More examples:
|
sort_by | no |
A list of numerical fields and their corresponding sort orders that will be used for ordering your results. Separate multiple fields with a comma. Up to 3 sort fields can be specified. E.g. The text similarity score is exposed as a special If one or two sorting fields are specified, Default: If no |
facet_by | no | A list of fields that will be used for faceting your results on. Separate multiple fields with a comma. |
max_facet_values | no | Maximum number of facet values to be returned. |
facet_query | no | Facet values that are returned can now be filtered via this parameter. The matching facet text is
also highlighted. For example, when faceting by |
num_typos | no | Number of typographical errors (1 or 2) that would be tolerated. Damerau–Levenshtein distance is used to calculate the number of errors. Default: |
page | no | Results from this specific page number would be fetched. |
per_page | no |
Number of results to fetch per page. Default: |
group_by | no | You can aggregate search results into groups or buckets by specify one or more
NOTE: To group on a particular field, it must be a faceted field. E.g. |
group_limit | no | Maximum number of hits to be returned for every group. If the Default: |
include_fields | no | Comma-separated list of fields from the document to include in the search result. |
exclude_fields | no | Comma-separated list of fields from the document to exclude in the search result. |
highlight_full_fields | no |
Comma separated list of fields which should be highlighted fully without snippeting. Default: all fields will be snippeted. |
highlight_affix_num_tokens | no |
The number of tokens that should surround the highlighted text on each side. Default: |
highlight_start_tag | no |
The start tag used for the highlighted snippets. Default: |
highlight_end_tag | no |
The end tag used for the highlighted snippets. Default: |
snippet_threshold | no | Field values under this length will be fully highlighted, instead of showing a snippet of relevant portion. Default: |
drop_tokens_threshold | no |
If the number of results found for a specific query is less than this number, Typesense will attempt
to drop the tokens in the query until enough results are found. Tokens that have the least individual hits
are dropped first. Set
Default: |
typo_tokens_threshold | no |
If the number of results found for a specific query is less than this number, Typesense will attempt to look for tokens with more typos until enough results are found.
Default: |
pinned_hits | no |
A list of records to unconditionally include in the search results at specific positions. An example use case would be to feature or promote certain items on the top of search results. A comma separated list of You could also use the Overrides feature to override search results based on rules. Overrides are applied first, followed by pinned_hits and finally hidden_hits. |
hidden_hits | no |
A list of records to unconditionally hide from search results. A comma separated list of You could also use the Overrides feature to override search results based on rules. Overrides are applied first, followed by pinned_hits and finally hidden_hits. |
id
.
client.collections('companies').documents('124').retrieve()
$client->collections['companies']->documents['124']->retrieve()
client.collections['companies'].documents['124'].retrieve()
client.collections['companies'].documents['124'].retrieve
$ curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X GET \
"http://localhost:8108/collections/companies/documents/124"
{
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}
GET ${TYPESENSE_HOST}/collections/:collection/documents/:id
Update an individual document from a collection by using its id
.
The update can be partial, as shown below:
let document = {
'company_name': 'Stark Industries',
'num_employees': 5500
}
client.collections('companies').documents('124').update(document)
$document = [
'company_name' => 'Stark Industries',
'num_employees' => 5500
]
$client->collections['companies']->documents['124']->update($document)
document = {
'company_name': 'Stark Industries',
'num_employees': 5500
}
client.collections['companies'].documents['124'].update(document)
document = {
'company_name' => 'Stark Industries',
'num_employees' => 5500
}
client.collections['companies'].documents['124'].update(document)
curl "http://localhost:8108/collections/companies/documents/124" -X PATCH \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-d '{
"company_name": "Stark Industries",
"num_employees": 5500
}'
{
"company_name": "Stark Industries",
"num_employees": 5500
}
PATCH ${TYPESENSE_HOST}/collections/:collection/documents/:id
Delete an individual document from a collection by using its id
.
client.collections('companies').documents('124').delete()
$client->collections['companies']->documents['124']->delete()
client.collections['companies'].documents('124').delete()
client.collections['companies'].documents['124'].delete
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X DELETE \
"http://localhost:8108/collections/companies/documents/124"
{
"id": "124",
"company_name": "Stark Industries",
"num_employees": 5215,
"country": "USA"
}
DELETE ${TYPESENSE_HOST}/collections/:collection/documents/:id
You can also delete a bunch of documents that match a specific filter condition:
client.collections('companies').documents().delete({'filter_by': 'num_employees:>100'})
$client->collections['companies']->documents->delete(['filter_by' => 'num_employees:>100']));
client.collections['companies'].documents.delete_({'filter_by': 'num_employees:>100'})
client.collections['companies'].documents.delete(filter_by: 'num_employees:>100')
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X DELETE \
"http://localhost:8108/collections/companies/documents?filter_by=num_employees:>=100&batch_size=100"
Use the batch_size
parameter to control the number of documents that should
deleted at a time. A larger value will speed up deletions, but will impact performance of other
operations running on the server.
{
"num_deleted": 24
}
DELETE ${TYPESENSE_HOST}/collections/:collection/documents?filter_by=X&batch_size=N
Retrieve the details of a collection, given its name.
client.collections('companies').retrieve()
$client->collections['companies']->retrieve()
client.collections['companies'].retrieve()
client.collections['companies'].retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X GET
"http://localhost:8108/collections/companies"
{
"name": "companies",
"num_documents": 1250,
"fields": [
{"name": "company_name", "type": "string"},
{"name": "num_employees", "type": "int32"},
{"name": "country", "type": "string", "facet": true}
],
"default_sorting_field": "num_employees"
}
GET ${TYPESENSE_HOST}/collections/:collection
client.collections('companies').documents().export()
$client->collections['companies']->documents->export()
client.collections['companies'].documents.export()
client.collections['companies'].documents.export
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X GET
"http://localhost:8108/collections/companies/documents/export"
{"id": "124", "company_name": "Stark Industries", "num_employees": 5215,\
"country": "US"}
{"id": "125", "company_name": "Future Technology", "num_employees": 1232,\
"country": "UK"}
{"id": "126", "company_name": "Random Corp.", "num_employees": 531,\
"country": "AU"}
GET ${TYPESENSE_HOST}/collections/:collection/documents/export
The documents to be imported can be either an array of document objects or be formatted as a newline delimited JSON string (see JSONL).
You can index multiple documents via the import API.
let documents = [{
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}]
client.collections('companies').documents().import(documents, {action: 'upsert'})
$documents = [[
'id' => '124',
'company_name' => 'Stark Industries',
'num_employees' => 5215,
'country' => 'USA'
]]
$client->collections['companies']->documents->import($documents, ['action' => 'upsert'])
documents = [{
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}]
client.collections['companies'].documents.import_(documents, {'action': 'upsert'})
documents = [{
'id' => '124',
'company_name' => 'Stark Industries',
'num_employees' => 5215,
'country' => 'USA'
}]
client.collections['companies'].documents.import(documents, action: 'upsert')
The other allowed action
modes are create
and update
.
create (default) | Creates a new document. Fails if a document with the same id already exists. |
upsert | Creates a new document or updates an existing document if a document with the same
id already exists. |
update | Updates an existing document. Fails if a document with the given id does not exist. |
You can feed the output of a Typesense export operation directly as import to the import end-point since both use JSONL.
Here's an example file:
{"id": "1", "company_name": "Stark Industries", "num_employees": 5215, "country": "USA"}
{"id": "2", "company_name": "Orbit Inc.", "num_employees": 256, "country": "UK"}
You can import the above documents.jsonl
file like this.
const documentsInJsonl = await fs.readFile("documents.jsonl");
client.collections('companies').documents().import(documentsInJsonl, {action: 'create'});
$documentsInJsonl = file_get_contents('documents.jsonl');
client.collections['companies'].documents.import($documentsInJsonl, ['action' => 'create'])
with open('documents.jsonl') as jsonl_file:
client.collections['companies'].documents.import_jsonl(jsonl_file.read(), {'action': 'create'})
documents_jsonl = File.read('documents.jsonl')
collections['companies'].documents.import(documents_jsonl, action: 'create')
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X POST --data-binary @documents.jsonl \
"http://localhost:8108/collections/companies/documents/import?action=create"
In the example above, we're importing the documents with the action
flag
set to create
. This means that the documents will be inserted only if a document with the
same id
is not already found.
As we have seen earlier, you can also use the upsert
and update
actions.
If you don't provide an action
, the default mode is create
.
By default, Typesense ingests 40 documents at a time into Typesense. To increase this value, use the
batch_size
parameter.
const documentsInJsonl = await fs.readFile("documents.jsonl");
client.collections('companies').documents().import(documentsInJsonl, {batch_size: 100});
$documentsInJsonl = file_get_contents('documents.jsonl');
client.collections['companies'].documents.import($documentsInJsonl, ['batch_size' => 100])
with open('documents.jsonl') as jsonl_file:
client.collections['companies'].documents.import_jsonl(jsonl_file.read(), {'batch_size': 100})
documents_jsonl = File.read('documents.jsonl')
collections['companies'].documents.import(documents_jsonl, batch_size: 100)
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X POST --data-binary @documents.jsonl \
"http://localhost:8108/collections/companies/documents/import?batch_size=100"
NOTE: Larger batch sizes will consume larger transient memory during import.
{"success": true}
{"success": true}
Each line of the response indicates the result of each document present in the request body (in the same order). If the import of a single document fails, it does not affect the other documents.
If there is a failure, the response line will include a corresponding error message and as well as the actual document content. For example, the second document had an import failure in the following response:
{"success": true}
{"success": false, "error": "Bad JSON.", "document": "[bad doc"}
POST ${TYPESENSE_HOST}/collections/:collection/documents/import
Returns a summary of all your collections. The collections are returned sorted by creation date, with the most recent collections appearing first.
client.collections().retrieve()
$client->collections->retrieve()
client.collections.retrieve()
client.collections.retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" "http://localhost:8108/collections"
[
{
"num_documents": 1250,
"name": "companies",
"fields": [
{"name": "company_name", "type": "string"},
{"name": "num_employees", "type": "int32"},
{"name": "country", "type": "string", "facet": true}
],
"default_sorting_field": "num_employees"
},
{
"num_documents": 1250,
"name": "ceos",
"fields": [
{"name": "company_name", "type": "string"},
{"name": "full_name", "type": "string"},
{"name": "from_year", "type": "int32"}
],
"default_sorting_field": "num_employees"
}
]
GET ${TYPESENSE_HOST}/collections
Permanently drops a collection. This action cannot be undone. For large collections, this might have an impact on read latencies.
client.collections('companies').delete()
$client->collections['companies']->delete()
client.collections['companies'].delete()
client.collections['companies'].delete
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -X DELETE
"http://localhost:8108/collections/companies"
{
"name": "companies",
"num_documents": 1250,
"fields": [
{"name": "company_name", "type": "string"},
{"name": "num_employees", "type": "int32"},
{"name": "country", "type": "string", "facet": true}
],
"default_sorting_field": "num_employees"
}
DELETE ${TYPESENSE_HOST}/collections/:collection
Typesense allows you to create API Keys with fine-grain access control. You can restrict access on both a per-collection and per-action level.
We will be using the initial bootstrap key that you started Typesense with (via --api-key
>)
to create additional keys. It's strongly recommended that you don't use the bootstrap
API key directly in your production applications. Instead you want to generate an appropriately-scoped key for the application at hand.
Let's begin by creating an API key that allows you to do all operations, i.e. it's effectively an admin key and
is equivalent to the key that you start Typesense with (via --api-key
).
key = client.keys().create({
'description': 'Admin key.',
'actions': ['*'],
'collections': ['*']
})
$key = $client->keys->create([
'description' => 'Admin key.',
'actions' => ['*'],
'collections' => ['*']
])
key = client.keys.create({
"description": "Admin key.",
"actions": ["*"],
"collections": ["*"]
})
key = client.keys.create({
'description' => 'Admin key.',
'actions' => ['*'],
'collections' => ['*']
})
curl 'http://localhost:8108/keys' -X POST -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{"description":"Admin key.","actions": ["*"], "collections": ["*"]}'
By setting both actions
and collections
to a wildcard ['*']
scope,
we're able to create an admin key that gives you universal access. However, you should refrain from creating
such widely scoped keys.
NOTE: The generated key is only returned during creation. You want to store this key carefully in a secure place.
Let's now see how we can create a search-only key that allows you to limit the key's scope to only the search action, and also for only a specific collection.
client.keys().create({
'description': 'Admin key.',
'actions': ['documents:search'],
'collections': ['companies']
})
$client->keys->create([
'description' => 'Search-only companies key.',
'actions' => ['documents:search'],
'collections' => ['companies']
])
client.keys.create({
"description": "Search-only companies key.",
"actions": ["documents:search"],
"collections": ["companies"]
})
client.keys.create({
'description' => 'Search-only companies key.',
'actions' => ['documents:search'],
'collections' => ['companies']
})
curl 'http://localhost:8108/keys' -X POST -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
-H 'Content-Type: application/json' \
-d '{"description":"Search-only companies key.","actions": ["documents:search"], "collections": ["companies"]}'
By setting the actions
scope to ["documents:search"]
and the collections
scope to ["companies"]
, we can generate a key that is allowed to only conduct searches on the
companies
collection.
{
"actions": [
"*"
],
"collections": [
"*"
],
"description": "Admin key.",
"id": 1,
"value": "k8pX5hD0793d8YQC5aD1aEPd7VleSuGP"
}
POST ${TYPESENSE_HOST}/keys
Parameter | Required | Description |
---|---|---|
actions | yes | List of allowed actions. See next table for possible values. |
collections | yes | List of collections that this key is scoped to. Supports regex. Eg: coll.* will match all collections that have "coll" in their name. |
description | no | Internal description to identify what the key is for |
expires_at | no | Unix timestamp until which the key is valid. |
Action | Description |
---|---|
documents:search |
Allows only search requests. |
documents:get |
Allows fetching a single document. |
collections:delete |
Allows a collection to be deleted. |
collections:create |
Allows a collection to be created. |
collections:* |
Allow all kinds of collection related operations. |
* |
Allows all operations. |
Retrieve (metadata about) a key.
key = client.keys(1).retrieve()
$key = $client->keys[1]->retrieve()
key = client.keys[1].retrieve()
key = client.keys[1].retrieve
curl 'http://localhost:8108/keys/1' -X GET -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"actions": [ "documents:search" ],
"collections": [ "*" ],
"description": "Search-only key.",
"id": 1,
"value_prefix": "vxpx"
}
Notice how only the key prefix is returned when you retrieve a key. Due to security reasons, only the create endpoint returns the full API key.
GET ${TYPESENSE_HOST}/keys/:id
Retrieve (metadata about) all keys.
client.keys().retrieve()
$client->keys->retrieve()
client.keys.retrieve()
client.keys.retrieve
curl 'http://localhost:8108/keys' -X GET -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"keys": [
{
"actions": [
"documents:search"
],
"collections": [
"users"
],
"description": "Search-only key.",
"id": 1,
"value_prefix": "iKBT"
},
{
"actions": [
"documents:search"
],
"collections": [
"users"
],
"description": "Search-only key.",
"id": 2,
"value_prefix": "wst8"
}
]
}
Notice how only the key prefix is returned when you retrieve a key. Due to security reasons, only the create endpoint returns the full API key.
GET ${TYPESENSE_HOST}/keys
Delete an API key given its ID.
key = client.keys(1).delete()
$key = $client->keys[1]->delete()
key = client.keys[1].delete()
key = client.keys[1].delete
curl 'http://localhost:8108/keys/1' -X DELETE -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"id": 1
}
DELETE ${TYPESENSE_HOST}/keys/:id
You can generate scoped search API keys that have embedded search parameters in them. This is useful for example when you have multi-tenant data indexed in your Typesense instance, but only want your users to access their own subset of the data.
To do this, you can embed a filter in a generated scoped search API key. When you use that key for search operations, those filters will get automatically applied and cannot be overriden.
We can generate scoped search API keys without having to make any calls to the Typesense server. We use an API key that we previously generated with a search scope, create an HMAC digest of the parameters with this key and use that as the API key. Our client libraries handle this logic for you, but you can also generate scoped search API keys from the command line.
Note: Remember to never expose your main search key client-side, since exposing the main search key will allow anyone to query the entire data set without your embedded search parameters.
keyWithSearchPermissions = 'RN23GFr1s6jQ9kgSNg2O7fYcAUXU7127'
client.keys().generateScopedSearchKey(keyWithSearchPermissions, {'filter_by': 'company_id:124', 'expires_at': 1611590465})
$keyWithSearchPermissions = 'RN23GFr1s6jQ9kgSNg2O7fYcAUXU7127'
$client->keys()->generateScopedSearchKey($keyWithSearchPermissions, ['filter_by' => 'company_id:124', 'expires_at' => 1611590465])
key_with_search_permissions = 'RN23GFr1s6jQ9kgSNg2O7fYcAUXU7127'
client.keys().generate_scoped_search_key(key_with_search_permissions, {"filter_by": "company_id:124", "expires_at": 1611590465})
key_with_search_permissions = 'RN23GFr1s6jQ9kgSNg2O7fYcAUXU7127'
client.keys().generate_scoped_search_key(key_with_search_permissions, {'filter_by': 'company_id:124', 'expires_at': 1611590465})
KEY_WITH_SEARCH_PERMISSIONS="RN23GFr1s6jQ9kgSNg2O7fYcAUXU7127"
EMBEDDED_SEARCH_PARAMETERS_JSON='{"filter_by":"company_id:124","expires_at":1611590465}'
digest=$(echo -n $EMBEDDED_SEARCH_PARAMETERS_JSON | openssl dgst -sha256 -hmac $KEY_WITH_SEARCH_PERMISSIONS -binary | base64)
scoped_api_key=$(echo -n "${digest}${KEY_WITH_SEARCH_PERMISSIONS:0:4}${EMBEDDED_SEARCH_PARAMETERS_JSON}" | base64)
echo $scoped_api_key
"SC9sT0hncHFwTHNFc3U3d3psRDZBUGNXQUViQUdDNmRHSmJFQnNnczJ4VT1STjIzeyJmaWx0ZXJfYnkiOiJjb21wYW55X2lkOjEyNCJ9"
You can also set a custom expires_at
for a scoped API key. The expiration for a scoped API key
should be less than the expiration of the parent API key with which it is generated.
While Typesense makes it really easy and intuitive to deliver great search results, sometimes you might want to promote certain documents over others. Or, you might want to exclude certain documents from a query's result set.
Using overrides, you can include or exclude specific documents for a given query.
In the following example, we are overriding the search results by placing the documents with ids 422
and 54
in the first and second positions respectively via the includes
condition.
Additionally, we're ensuring that the document with id 287
is not returned at all
via the excludes
condition. You need to specify only one of exclude
or
include
.
Note how we are applying these overrides to an exact
match of the query apple
.
Instead, if we want to match all queries that contained the word apple
, we will use
the contains
match instead.
override = {
"rule": {
"query": "apple",
"match": "exact"
},
"includes": [
{"id": "422", "position": 1},
{"id": "54", "position": 2}
],
"excludes": [
{"id": "287"}
]
}
// Creates/updates an override called `customize-apple` in the `companies` collection
client.collections('companies').overrides().upsert('customize-apple', override)
$override = [
"rule" => [
"query" => "apple",
"match" => "exact"
],
"includes" => [
["id" => "422", "position" => 1],
["id" => "54", "position" => 2]
],
"excludes" => [
["id" => "287"]
]
]
# Creates/updates an override called `customize-apple` in the `companies` collection
$client->collections['companies']->overrides->upsert('customize-apple', $override)
override = {
"rule": {
"query": "apple",
"match": "exact"
},
"includes": [
{"id": "422", "position": 1},
{"id": "54", "position": 2}
],
"excludes": [
{"id": "287"}
]
}
# Creates/updates an override called `customize-apple` in the `companies` collection
client.collections['companies'].overrides.upsert('customize-apple', override)
override = {
"rule" => {
"query" => "apple",
"match" => "exact"
},
"includes" => [
{"id" => "422", "position" => 1},
{"id" => "54", "position" => 2}
],
"excludes" => [
{"id" => "287"}
]
}
# Creates/updates an override called `customize-apple` in the `companies` collection
client.collections['companies'].overrides.upsert('customize-apple', override)
curl "http://localhost:8108/collections/companies/overrides/customize-apple" -X PUT \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -d '{
"rule": {
"query": "apple",
"match": "exact"
},
"includes": [
{"id": "422", "position": 1},
{"id": "54", "position": 2}
],
"excludes": [
{"id": "287"}
]
}'
{
"id": "customize-apple",
"excludes": [
{
"id": "287"
}
],
"includes": [
{
"id": "422",
"position": 1
},
{
"id": "54",
"position": 2
}
],
"rule": {
"match": "exact",
"query": "apple"
}
}
PUT ${TYPESENSE_HOST}/collections/:collection/overrides/:id
Parameter | Required | Description |
---|---|---|
excludes | no | List of document id s that should be excluded from the search results. |
includes | no | List of document id s that should be included in the search results with their
corresponding position s. |
rule.query | yes | Indicates what search queries should be overridden. |
rule.match | yes | Indicates whether the match on the query term should be exact or contains . |
Listing all overrides associated with a given collection.
client.collections('companies').overrides().retrieve
$client->collections['companies']->overrides->retrieve()
client.collections['companies'].overrides.retrieve()
client.collections['companies'].overrides.retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/collections/companies/overrides"
{
"overrides":[
{
"id":"customize-apple",
"excludes":[
{
"id":"287"
}
],
"includes":[
{
"id":"422",
"position":1
},
{
"id":"54",
"position":2
}
],
"rule":{
"match":"exact",
"query":"apple"
}
}
]
}
GET ${TYPESENSE_HOST}/collections/:collection/overrides
Deleting an override associated with a collection.
client.collections('companies').overrides('customize-apple').delete()
$client->collections['companies']->overrides['customize-apple'].delete()
client.collections['companies'].overrides['customize-apple'].delete()
client.collections['companies'].overrides['customize-apple'].delete
curl "http://localhost:8108/collections/companies/overrides/customize-apple" -X DELETE \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"id": "customize-apple"
}
DELETE ${TYPESENSE_HOST}/collections/:collection/overrides/:id
An alias is a virtual collection name that points to a real collection. If you're familiar with symbolic links on Linux, it's very similar to that.
Aliases are useful when you want to reindex your data in the background on a new collection and switch your application to it without any changes to your code. Let's take an example.
Let's say we have a collection called companies_june10
and an alias
called companies
pointing to that collection.
collection ---> companies_june10
On the next day (June 11), we will create a new collection called companies_june11
and start indexing the documents in the background into this collection. When we are done indexing,
if we updated the companies
alias to point to this new collection,
your application would immediately start querying against the freshly indexed collection.
collection ---> companies_june11
Convenient isn't it? Let's now look at how we can create, update and manage aliases.
aliased_collection = {
'collection_name': 'companies_june11'
}
// Creates/updates an alias called `companies` to the `companies_june11` collection
client.aliases().upsert('companies', aliased_collection)
$aliasedCollection = [
'collection_name' => 'companies_june11'
]
# Creates/updates an alias called `companies` to the `companies_june11` collection
$client->aliases->upsert('companies', $aliasedCollection)
aliased_collection = {
'collection_name': 'companies_june11'
}
# Creates/updates an alias called `companies` to the `companies_june11` collection
client.aliases.upsert('companies', aliased_collection)
aliased_collection = {
'collection_name' => 'companies_june11'
}
# Creates/updates an alias called `companies` to the `companies_june11` collection
client.aliases.upsert('companies', aliased_collection)
curl "http://localhost:8108/aliases/companies" -X PUT \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -d '{
"collection_name": "companies_june11"
}'
{
"name": "companies",
"collection_name": "companies_june11",
}
PUT ${TYPESENSE_HOST}/aliases/:alias
Parameter | Required | Description |
---|---|---|
collection_name | yes | Name of the collection you wish to map the alias to. |
We can find out which collection an alias points to by fetching it.
client.aliases('companies').retrieve()
$client->aliases['companies']->retrieve()
client.aliases['companies'].retrieve()
client.aliases['companies'].retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/aliases/companies"
{
"name": "companies",
"collection_name": "companies_june11",
}
GET ${TYPESENSE_HOST}/aliases/:alias
List all aliases and the corresponding collections that they map to.
client.aliases().retrieve()
$client->aliases->retrieve()
client.aliases.retrieve()
client.aliases.retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/aliases"
{
"aliases": [
{
"name": "companies",
"collection_name": "companies_june11"
},
{
"name": "employees",
"collection_name": "employees_june11"
}
]
}
GET ${TYPESENSE_HOST}/aliases
client.aliases('companies').delete()
$client->aliases['companies']->delete()
client.aliases['companies'].delete()
client.aliases['companies'].delete
curl "http://localhost:8108/aliases/companies" -X DELETE
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"name": "companies",
"collection_name": "companies_june11"
}
DELETE ${TYPESENSE_HOST}/aliases/:alias
The synonyms feature allows you to define search terms that should be considered equivalent.
For eg: when you define a synonym for sneaker
as shoe
,
searching for sneaker
will now return all records with the word shoe
in them,
in addition to records with the word sneaker
.
Typesense supports two types of synonyms:
ABC, DEF and XYZ
(for eg) as multi-way synonyms will cause searches for any one of those words (eg: DEF
) to return records containing at least one of the words in the synonym set (eg: records with ABC
or DEF
or KYX
are returned).DEF
and XYZ
as one-way synonyms of ABC
will cause searches for
DEF
or XYZ
to return records containing ABC
.
synonym = {
"synonyms": ["blazer", "coat", "jacket"]
}
// Creates/updates a synonym called `coat-synonyms` in the `products` collection
client.collections('products').synonyms().upsert('coat-synonyms', synonym)
$synonym = [
"synonyms" => ["blazer", "coat", "jacket"]
]
# Creates/updates a synonym called `coat-synonyms` in the `products` collection
$client->collections['products']->synonyms->upsert('coat-synonyms', $synonym)
synonym = {
"synonyms": ["blazer", "coat", "jacket"]
}
# Creates/updates a synonym called `coat-synonyms` in the `products` collection
client.collections['products'].synonyms.upsert('coat-synonyms', synonym)
synonym = {
"synonyms" => ["blazer", "coat", "jacket"]
}
# Creates/updates a synonym called `coat-synonyms` in the `products` collection
client.collections['products'].synonyms.upsert('coat-synonyms', synonym)
curl "http://localhost:8108/collections/products/synonyms/coat-synonyms" -X PUT \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -d '{
"synonyms": ["blazer", "coat", "jacket"]
}'
{
"id": "coat-synonyms",
"synonyms": ["blazer", "coat", "jacket"]
}
synonym = {
"root": "blazer",
"synonyms": ["coat", "jacket"]
}
// Creates/updates a synonym called `blazer-synonyms` in the `products` collection
client.collections('products').synonyms().upsert('blazer-synonyms', synonym)
$synonym = [
"root" => "blazer",
"synonyms" => ["coat", "jacket"]
]
# Creates/updates a synonym called `blazer-synonyms` in the `products` collection
$client->collections['products']->synonyms->upsert('blazer-synonyms', $synonym)
synonym = {
"root": "blazer",
"synonyms": ["coat", "jacket"]
}
# Creates/updates a synonym called `blazer-synonyms` in the `products` collection
client.collections['products'].synonyms.upsert('blazer-synonyms', synonym)
synonym = {
"root" => "blazer",
"synonyms" => ["coat", "jacket"]
}
# Creates/updates a synonym called `coat-synonyms` in the `products` collection
client.collections['products'].synonyms.upsert('coat-synonyms', synonym)
curl "http://localhost:8108/collections/products/synonyms/coat-synonyms" -X PUT \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" -d '{
"root": "blazer",
"synonyms": ["coat", "jacket"]
}'
{
"id":"coat-synonyms",
"root":"blazer",
"synonyms": ["coat", "jacket"]
}
PUT ${TYPESENSE_HOST}/collections/:collection/synonyms/:id
Parameter | Required | Description |
---|---|---|
synonyms | yes | Array of words that should be considered as synonyms. |
root | no | For 1-way synonyms, indicates the root word that words in the synonyms parameter map to. |
We can retrieve a single synonym.
client.collections('products').synonyms('coat-synonyms').retrieve
$client->collections['products']->synonyms['coat-synonyms']->retrieve()
client.collections['products'].synonyms['coat-synonyms'].retrieve()
client.collections['products'].synonyms['coat-synonyms'].retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/collections/products/synonyms/coat-synonyms"
{
"id": "coat-synonyms",
"root":"",
"synonyms": ["blazer", "coat", "jacket"]
}
GET ${TYPESENSE_HOST}/collections/:collection/synonyms/:id
List all synonyms associated with a given collection.
client.collections('products').synonyms().retrieve
$client->collections['products']->synonyms->retrieve()
client.collections['products'].synonyms.retrieve()
client.collections['products'].synonyms.retrieve
curl -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
"http://localhost:8108/collections/products/synonyms"
{
"synonyms":[
{
"id": "coat-synonyms",
"root": "blazer",
"synonyms": ["coat", "jacket"]
}
]
}
GET ${TYPESENSE_HOST}/collections/:collection/synonyms
Delete a synonym associated with a collection.
client.collections('books').synonyms('coat-synonyms').delete()
$client->collections['books']->synonyms['coat-synonyms'].delete()
client.collections['books'].synonyms['coat-synonyms'].delete()
client.collections['books'].synonyms['coat-synonyms'].delete
curl "http://localhost:8108/collections/books/synonyms/coat-synonyms" -X DELETE \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"id": "coat-synonyms"
}
DELETE ${TYPESENSE_HOST}/collections/:collection/synonyms/:id
Creates a point-in-time snapshot of a Typesense node's state and data in the specified directory.
You can then backup the snapshot directory that gets created and later restore it as a data directory, as needed.
client.operations.perform('snapshot', {'snapshot_path': '/tmp/typesense-data-snapshot'})
$client->operations->perform("snapshot", ["snapshot_path" => "/tmp/typesense-data-snapshot"])
client.operations.perform('snapshot', {'snapshot_path': '/tmp/typesense-data-snapshot'})
client.operations.perform('snapshot', {'snapshot_path': '/tmp/typesense-data-snapshot'})
curl "http://localhost:8108/operations/snapshot?snapshot_path=/tmp/typesense-data-snapshot" -X POST \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"success": true
}
POST ${TYPESENSE_HOST}/operations/snapshot
Parameter | Required | Description |
---|---|---|
snapshot_path | yes | The directory on the server where the snapshot should be saved. |
Triggers a follower node to initiate the raft voting process, which triggers leader re-election.
The follower node that you run this operation against will become the new leader, once this command succeeds.
client.operations.perform('vote')
$client->operations->perform("vote")
client.operations.perform('vote')
client.operations.perform('vote')
curl "http://localhost:8108/operations/vote" -X POST \
-H "Content-Type: application/json" \
-H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}"
{
"success": true
}
POST ${TYPESENSE_HOST}/operations/vote
This release contains a few new features and important bug fixes.
Typesense API uses standard HTTP response codes to indicate the success or failure of a request.
Codes in the 2xx range indicate success, codes in the 4xx range indicate an error given the information provided (e.g. a required parameter was omitted), and codes in the 5xx range indicate an error with the Typesense service itself.
Error Code | Meaning |
---|---|
400 | Bad Request - The request could not be understood due to malformed syntax. |
401 | Unauthorized - Your API key is wrong. |
404 | Not Found - The requested resource is not found. |
409 | Conflict - When a resource already exists. |
422 | Unprocessable Entity - Request is well-formed, but cannot be processed. |
503 | Service Unavailable - We’re temporarily offline. Please try again later. |