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.
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.
Option | Type | Default | Usage |
---|---|---|---|
searchIndex | boolean | True | To enable/disable indexing on a field. Any non-indexed field won't be searchable. |
sort | boolean | False | To enable/disable sorting on a field. Not supported for Arrays and Objects without a predefined schema. |
facet | boolean | False | To enable/disable faceting on a field. Not supported for Array of Objects. |
elements | TigrisDataTypes | Required for Array fields | The type of the elements in the array. |
@TigrisSearchIndex("catalog")
export class Catalog {
@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>;
}
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.
The Tigris TypeScript client repository has more examples for defining complex schemas.
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>;
}
Array of array(s)​
To model your search index with nested arrays, additional depth
option is required
in @SearchField()
annotation. depth
identifies the depth of your nested array. E.g - field of
type Array<Array<Array<Array<string>>>>
would have depth = 4.
export class Cell {
@SearchField()
x: number;
@SearchField()
y: number;
@SearchField()
value: string;
}
@TigrisSearchIndex("matrices")
export class Matrix {
@SearchField({ facet: false })
id: string;
@SearchField({ elements: Cell, depth: 3 })
cells: Array<Array<Array<Cell>>>;
}
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 specify an id
field in the schema.