Skip to main content

Search Modeling

The first step is to define search models as part of your application code. The data conforming to these models is stored as JSON documents and indexed in Tigris to facilitate searches.

note

You do not need to have all the fields present in your document, defined in the search model, only the fields that you need to be searchable. When you store documents in the search index, we store the entire document including the fields that are not defined in the search model

Declaring Models

With the Tigris TypeScript client you can define your data models using Decorated classes or Interfaces. The use of Decorators is recommended and is covered in this section. If you prefer to use Interfaces, you can refer to the Interfaces section.

Below we describe how the search models can be defined.

Tigris client uses @TigrisSearchIndex("search-index-name") decorator on a class to identify a schema (search model) for the index. Requires a string input as the name of this search index.

export const CATALOG_INDEX_NAME = "catalog";

@TigrisSearchIndex(CATALOG_INDEX_NAME)
class Catalog {
@SearchField()
name: string;

@SearchField()
price: number;

@SearchField()
brand: string;

@SearchField()
labels: string;

@SearchField(TigrisDataTypes.INT32)
popularity: number;

@SearchField()
entryDate: Date;

@SearchField()
available: boolean;
}

For the properties in the class to be made searchable, they need to be annotated with the @SearchField() annotation. The data type is determined using "reflection" if the optional type parameter is not specified. A @SearchField() decorator accepts optional parameters to further refine how the document field is indexed.

OptionTypeDefaultUsage
searchIndexbooleanTrueTo enable/disable indexing on a field. Any non-indexed field won't be searchable.
sortbooleanFalseTo enable/disable sorting on a field. Not supported for Arrays and Objects without a predefined schema.
facetbooleanFalseTo enable/disable faceting on a field. Not supported for Array of Objects.
dimensionsnumberRequired for vector fieldsThe number of dimensions of the vector embeddings that will be stored.
elementsTigrisDataTypesRequired for Array fieldsThe type of the elements in the array.
idbooleanFalseTo have this field's value used as the document ID for documents in the search index. The field must be of string type.
@TigrisSearchIndex("catalog")
export class Catalog {
@SearchField({ id: true })
catalogId: string;

@SearchField({ sort: true })
name: string;

@SearchField({ sort: true })
price: number;

@SearchField({ facet: true })
brand: string;

@SearchField({ elements: TigrisDataTypes.STRING, facet: true })
@Field({ elements: TigrisDataTypes.STRING })
tags: Array<string>;

@SearchField({ dimensions: 1536 })
vector: number[];
}
info

Documents that you store in a search index can have fields that are not annotated with @SearchField(). These fields are not searchable. A common use-case is where you have a document with ten fields and you only want five of the fields to be searchable but would like to store the entire document.

Additionally, it is possible to turn sorting or faceting on or off for the model in the search index at any time without the need to drop the index.

The Tigris TypeScript client repository has more examples for defining complex schemas.

Storing Vector Embeddings

An embedding is a vector representation of a document. Embeddings are generated by a machine learning model. The vector representation is a dense vector of floating-point numbers that can be used to find similar documents.

To store vector embeddings in Tigris, you need to define a field as follows:

@SearchField({ dimensions: 1536 })
vector: number[];

Indexing Embedded Documents

Tigris supports rich document structures. For example, you can embed related data in a single document. Embedded models allow application to fetch data with fewer queries, thus reducing query activity and increasing efficiency.

Below is an example of embedded model. We first define the ProductItem type and then embed it inside the Order type.

export class ProductItem {
@SearchField()
productId: string;

@SearchField()
quantity: number;
}

@TigrisSearchIndex("orders")
export class Order {
@SearchField()
userId: bigint;

@SearchField()
orderTotal: number;

@SearchField({ elements: ProductItem })
productItems: Array<ProductItem>
}

Arrays in documents

Including arrays in your schema requires elements option to identify type of elements when using @SearchField() decorator.

@TigrisSearchIndex("cities")
export class City {
@SearchField()
name: string;

@SearchField({ elements: TigrisDataTypes.STRING })
neighborhoods: Array<string>;
}

Create a Search Index

Tigris provides an easy to use way to create or modify search indexes.

const client = new Tigris();
const search = client.getSearch();
const catalog = await search.createOrUpdateIndex<Catalog>(
Catalog
);

id field in a document

Every indexed document in Tigris has an id field of string type to uniquely identify it. The id can be used to get, replace or delete a document in search index. id is immutable.

Tigris assigns an auto-generated id to each document. However, there might be cases where you want to supply your own ID, for example to avoid duplicate documents to be indexed. In such cases you can annotate a field that can uniquely identify a document with @SearchField({ id: true }) as shown below.

@SearchField({ id: true })
catalogId: string;