Entity Decorators
Kinotic provides a set of decorators to control how entity fields are stored, indexed, and queried. All decorators are imported from @kinotic-ai/persistence.
Field Decorators
@NotNull
Marks a field as required. The server will reject saves where this field is missing or null.
@NotNull
name: string = ''
@Text
Enables full-text search indexing on a string field. Without this decorator, string fields are indexed as keywords (exact match only). With @Text, you can perform partial and fuzzy text searches.
@Text
description: string = ''
@Precision
Controls the numeric precision used for storage and indexing. By default, numbers are stored as integers.
import { Precision, PrecisionType } from '@kinotic-ai/persistence'
@Precision(PrecisionType.SHORT)
age: number = 0
@Precision(PrecisionType.DOUBLE)
price: number = 0.0
Available PrecisionType values:
| Type | Description |
|---|---|
SHORT | 16-bit integer |
INT | 32-bit integer (default for numbers) |
LONG | 64-bit integer |
FLOAT | 32-bit floating point |
DOUBLE | 64-bit floating point |
@NotIndexed
Excludes a field from indexing. The field is still stored and returned in query results, but you cannot search or filter by it. Useful for large text blobs or fields that do not need to be queried.
@NotIndexed
notes: string = ''
@Flattened
Optimizes storage for dynamic key-value data where the keys are not known ahead of time. Flattened fields support keyword-level queries on both keys and values.
@Flattened
metadata: Record<string, any> = {}
@Nested
Preserves the independence of each element in an array of objects. This allows you to query individual elements without cross-matching between them.
@Nested
addresses: Address[] = []
Without @Nested, arrays of objects are flattened, which can produce unexpected results when querying across multiple fields of array elements.
Relationship Decorators
@Discriminator
Enables polymorphic (union) types. Apply @Discriminator to a property that determines the concrete type of the entity. This allows a single entity collection to store multiple subtypes.
import { Entity, AutoGeneratedId, Discriminator, MultiTenancyType } from '@kinotic-ai/persistence'
@Entity(MultiTenancyType.NONE)
export class Pet {
@AutoGeneratedId
id: string | null = null
@Discriminator
type: string = ''
}
export class Dog extends Pet {
breed: string = ''
}
export class Cat extends Pet {
lives: number = 9
}
Only the base class needs the @Entity decorator. Subclasses inherit the entity configuration. The discriminator field value is used during deserialization to determine which subclass to instantiate.
Versioning
@Version
Enables optimistic locking on the entity. When an entity with a @Version field is updated, the server checks that the version matches the current stored version. If another update occurred in between, the save is rejected with a conflict error. The field type must be string | null.
@Version
version: string | null = null
This is useful for preventing lost updates in concurrent environments.
Time Series
@TimeReference
Marks the time field for stream entities (EntityType.STREAM). This field is used as the timestamp for time-series indexing and partitioning.
import { Entity, AutoGeneratedId, TimeReference, MultiTenancyType, EntityType } from '@kinotic-ai/persistence'
@Entity(MultiTenancyType.NONE, EntityType.STREAM)
export class SensorReading {
@AutoGeneratedId
id: string | null = null
@TimeReference
timestamp: Date = new Date()
value: number = 0.0
}
For a complete reference of all decorators, see the Decorators Reference.