Skip to main content

Using Interfaces

We recommend using Classes and Decorators to define the data model. However, if you prefer to not use class decorators you can define the collection schema using Interfaces. This section describes how to define the data model using Interfaces.

Declaring Models

Below we describe how the database models can be defined.

// data container
interface Catalog extends TigrisCollectionType {
id?: string;
name: string;
price: number;
brand: string;
labels: string;
popularity: number;
entryDate: Date;
available: boolean;
}

// schema definition
const catalogSchema: TigrisSchema<Catalog> = {
id: {
type: TigrisDataTypes.STRING,
primary_key: {
order: 1,
autoGenerate: true,
},
},
name: {
type: TigrisDataTypes.STRING,
},
price: {
type: TigrisDataTypes.NUMBER,
},
brand: {
type: TigrisDataTypes.STRING,
},
labels: {
type: TigrisDataTypes.STRING,
},
popularity: {
type: TigrisDataTypes.INT32,
},
entryDate: {
type: TigrisDataTypes.DATE_TIME,
timestamp: "createdAt"
},
available: {
type: TigrisDataTypes.BOOLEAN,
default: false
},
};

Essentially, schema is modeled as two parts:

  1. Data containers - interface that holds the data model
  2. Schema of Data containers - TigrisSchema definition of these data containers.
// data container
interface Catalog extends TigrisCollectionType {
id?: string;
name: string;
}

// schema definition
const catalogSchema: TigrisSchema<Catalog> = {
id: {
type: TigrisDataTypes.INT64,
primary_key: {
order: 1,
autoGenerate: true,
},
},
name: { type: TigrisDataTypes.STRING },
};
info

You must keep the data container and schema definition in sync.

Embedded Data Model

Tigris offers rich documents that enable embedding related data in a single document. Embedded models allow applications to complete database operations with fewer queries or updates, thus reducing query activity and increasing efficiency.

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

// data containers
export interface ProductItem {
productId: string;
quantity: number;
}
export interface Order extends TigrisCollectionType {
orderId?: string;
userId: bigint;
orderTotal: number;
productItems: ProductItem[];
}

// schema definitions
const productItemSchema: TigrisSchema<ProductItem> = {
productId: {
type: TigrisDataTypes.STRING,
},
quantity: {
type: TigrisDataTypes.NUMBER,
},
};
export const orderSchema: TigrisSchema<Order> = {
orderId: {
type: TigrisDataTypes.INT64,
primary_key: {
order: 1,
autoGenerate: true,
},
},
userId: {
type: TigrisDataTypes.NUMBER_BIGINT,
},
orderTotal: {
type: TigrisDataTypes.NUMBER,
},
productItems: {
type: TigrisDataTypes.ARRAY,
items: {
type: productItemSchema,
},
},
};

Arrays in documents

Including arrays in your schema requires items attribute to identify its contents.

export interface City extends TigrisCollectionType {
name: string;
neighborhoods: Array<string>;
}

export const CitySchema: TigrisSchema<City> = {
name: {
type: TigrisDataTypes.STRING,
primary_key: {
order: 1
}
},
neighborhoods: {
type: TigrisDataTypes.ARRAY,
items: {
type: TigrisDataTypes.STRING
},
},
};

Array of array(s)

Following example demonstrates a collection schema with nested arrays:

export interface Cell {
x: number;
y: number;
value: string;
}

export interface Matrix extends TigrisCollectionType {
id: string;
cells: Array<Array<Array<Cell>>>;
}

export const MatrixSchema: TigrisSchema<Matrix> = {
id: {
type: TigrisDataTypes.STRING,
primary_key: {
order: 1
}
},
cells: {
type: TigrisDataTypes.ARRAY,
items: {
type: TigrisDataTypes.ARRAY,
items: {
type: TigrisDataTypes.ARRAY,
items: {
type: {
x: {
type: TigrisDataTypes.NUMBER,
},
y: {
type: TigrisDataTypes.NUMBER,
},
value: {
type: TigrisDataTypes.STRING,
},
},
},
},
},
},
};

Create a Collection

Creates a collection with the model and any new operation will see the changes.

const catalog = await db.createOrUpdateCollection<Catalog>(
"catalog",
catalogSchema
);

Drop a Collection

Drops a collection with the model and any new operation will see the changes.

await db.dropCollection(Catalog);

List Collections

Lists all the collections in the database.

await db.listCollections();

Drop all Collections

Drops all collections in the database.

await db.dropAllCollections(Catalog);

Data Types

Tigris supports the majority of the primitive TypeScript types while also providing support for custom types.

  • primitive types: string, boolean, number, bigint, Date, object.
  • Custom types: user-defined class to define custom types.
  • Array and object of all of above is supported.

Working with 64-bit integers (BigInt)

If your collection field has a use-case for 64-bit integers, we recommend using bigint or string field type to represent your integers. If chose to use bigint primitive type, please enable {supportBigInt: true} flag in the client configuration.

64-bit integers using String

// data container
export interface CatalogCategory {
name: string;
code: string;
}

// schema definition
export const categorySchema: TigrisSchema<CatalogCategory> = {
name: {
type: TigrisDataTypes.STRING,
},
code: {
type: TigrisDataTypes.NUMBER_BIGINT,
},
};

64-bit integers using BigInt

const tigris = new Tigris({
serverUrl: "api.preview.tigrisdata.cloud",
clientId: "paste client_id here",
clientSecret: "paste client_secret here",
projectName: "paste project name here",
supportBigInt: true
});

// data container
export interface CatalogCategory {
name: string;
code: bigint;
}

// schema definition
export const categorySchema: TigrisSchema<CatalogCategory> = {
name: {
type: TigrisDataTypes.STRING,
},
code: {
type: TigrisDataTypes.NUMBER_BIGINT,
},
};

Primary Key

A primary key uniquely identifies a document in the collection and enforces the unique constraint. In the absence of a user-defined primary key, it is auto-generated.

Defining a Primary Key

The example above demonstrates how primary key is defined. The order attribute in primaryKey represents the order of the field in the primary key. While autoGenerate: true represents that the values for this field will be automatically generated by the Tigris server.

Composite Primary Key

Composite primary keys are also supported but in case of composite keys order of the fields is important. The example below demonstrates how the order of the fields are defined in case of a composite primary key.

// data container
interface Catalog extends TigrisCollectionType {
id?: number;
name: string;
}

// schema definition
const catalogSchema: TigrisSchema<Catalog> = {
id: {
type: TigrisDataTypes.INT32,
primary_key: {
order: 1,
autoGenerate: true,
},
},
name: {
type: TigrisDataTypes.STRING,
primary_key: {
order: 2,
},
},
};

Modifying Schema

Step 1: Update the data model in your application code

// data containers
export interface ProductAttributes {
name: string;
value: string;
}

export interface Catalog extends TigrisCollectionType {
id: bigint;
name: string;
price: number;
attributes: Array<ProductAttributes>;
+ brand: string
}

// schema definitions
const attributesSchema: TigrisSchema<ProductAttributes> {
name: {
type: TigrisDataTypes.STRING,
},
value: {
type: TigrisDataTypes.STRING,
}
}

const catalogSchema: TigrisSchema<Catalog> {
id: {
type: TigrisDataTypes.INT64,
primary_key: {
order: 1,
autoGenerate: true,
},
},
name: {
type: TigrisDataTypes.STRING,
},
price: {
type: TigrisDataTypes.NUMBER,
},
attributes: {
type: TigrisDataTypes.ARRAY,
items: {
attributesSchema
}
},
+ brand: {
+ type: TigrisDataTypes.STRING,
+ },
}

Step 2: Update the Collection

Updates the collection with the new model and any new operation will see the changes.

const catalog = await db.createOrUpdateCollection<Catalog>(
"catalog",
catalogSchema
);