Skip to content

Basics

The following are the steps to define a basic entity:

DecoratorPurpose
@Entity()Marks a class as a database table/collection. Accepts options: name (custom table name), softDelete (enable soft-delete).
@Id()Defines the Primary Key with support for onInsert generators (UUIDs, etc).
@Field()Standard column. Use { references: ... } for Foreign Keys.
@Index()Defines a composite or customized index on one or more columns.
@OneToOneDefines a one-to-one relationship.
@OneToManyDefines a one-to-many relationship.
@ManyToOneDefines a many-to-one relationship.
@ManyToManyDefines a many-to-many relationship.
import { v7 as uuidv7 } from 'uuid';
import { Entity, Id, Field, Index } from 'uql-orm';
@Entity()
export class User {
@Id({
type: 'uuid',
onInsert: () => uuidv7()
})
id?: string;
@Field({ index: true })
name?: string;
@Field({
unique: true,
comment: 'User login email'
})
email?: string;
@Field({ type: 'text' })
bio?: string;
}

UQL provides two levels for specifying column types. Always prefer type for portability; use columnType only for precise SQL control.

PropertyLevelDescription
typeLogical (Recommended)Database-agnostic. UQL maps it to the correct SQL type for each dialect.
columnTypePhysicalDirect SQL type. Use only when you need exact control over the underlying type.
// ✅ RECOMMENDED: Use `type` for semantic, cross-database types
@Field({ type: 'uuid' })
externalId?: string;
@Field({ type: 'jsonb' })
metadata?: Json<{ theme?: string; priority?: number }>;
@Field({ type: 'text' })
bio?: string;
// ⚠️ USE SPARINGLY: `columnType` for precise SQL control
@Field({
columnType: 'decimal',
precision: 10,
scale: 2
})
price?: number;
@Field({
columnType: 'varchar',
length: 500
})
longBio?: string;

The @Field and @Id decorators accept several options for both query validation and schema generation:

OptionTypeDescription
namestringCustom database column name.
typeType | stringLogical type: String, Number, Boolean, Date, BigInt, or strings like 'uuid', 'text', 'json', 'jsonb', 'timestamp', 'timestamptz', 'vector', 'halfvec', 'sparsevec'.
columnTypeColumnTypeExplicit SQL column type (e.g., varchar, text, jsonb, vector, halfvec, sparsevec). Takes highest priority.
lengthnumberColumn length. If unspecified, defaults to TEXT (Postgres/SQLite) or VARCHAR(255) (MySQL/Maria).
nullablebooleanWhether the column allows NULL values. Defaults to true.
uniquebooleanAdds a UNIQUE constraint.
indexboolean | stringAdds an index. Pass a string to name it.
defaultValueScalarDefault value at the database level.
commentstringAdds a comment to the column in the database.
dimensionsnumberNumber of dimensions for vector fields. E.g., @Field({ type: 'vector', dimensions: 1536 }).
distanceVectorDistanceDefault distance metric for vector similarity queries: 'cosine', 'l2', 'inner', 'l1', 'hamming'.
onInsertfunctionGenerator function for new records (e.g., () => uuidv7()).
onUpdatefunctionCallback invoked on every update (e.g., () => new Date() for updatedAt).
onDeletefunctionCallback for soft-delete values (e.g., () => new Date()).
updatablebooleanSet to false to prevent updates on this field (e.g., createdAt). Defaults to true.
eagerbooleanWhether this relation is eagerly loaded. Defaults to true.
virtualRawExpressionDefines a computed/virtual field via raw SQL.
references() => EntityMarks this field as a foreign key referencing another entity’s primary key.
foreignKeystring | falseCustom foreign key constraint name, or false to disable physical constraints while maintaining logical references.

The @Id decorator also supports:

OptionTypeDescription
autoIncrementbooleanExplicitly enable/disable auto-increment. Defaults to true for numeric types, false for strings/UUIDs.
// Auto-increment integer (simple, database-managed)
@Id()
id?: number;
// UUID (portable, client-generated)
@Id({
type: 'uuid',
onInsert: () => uuidv7()
})
id?: string;