BaasixBaasix

Schema Reference Guide

Note: API-style reference for defining schemas. For a conceptual overview, patterns, and best practices, see Database Schema & Relationships Guide.

← Back to Documentation Home

Table of Contents

  1. Introduction
  2. Schema Structure
  3. Field Types
  4. Field Properties
  5. Relationships
  6. Schema Properties
  7. Indexing
  8. Default Values
  9. Examples
  10. Best Practices

Introduction

In BAASIX, schemas define the structure of your data collections. A schema specifies the fields, their types, relationships between collections, and other properties that determine how data is stored and validated.

Schema Structure

A schema definition contains the following key components:

{
  "collectionName": "products",
  "schema": {
    "name": "Product",
    "timestamps": true,
    "paranoid": true,
    "freezeTableName": true,
    "fields": {
      // Field definitions go here
    },
    "indexes": [
      // Index definitions go here
    ]
  }
}
PropertyTypeDescription
collectionNamestringName of the database collection/table
schemaobjectObject containing the schema definition
schema.namestringDisplay name of the schema
schema.timestampsbooleanAdd createdAt and updatedAt fields automatically (default: true)
schema.paranoidbooleanEnable soft deletes with deletedAt field (default: false)
schema.freezeTableNamebooleanPrevent pluralization of table name (default: false)
schema.fieldsobjectObject containing field definitions
schema.indexesarrayArray of index definitions

Field Types

BAASIX supports the following field types. For a complete guide on filtering these types, see Complete Filter Reference.

Supported Field Type Categories:

  • String Types: String, Text, CiText, TOKEN
  • Numeric Types: Integer, BigInt, Real, Double, Decimal
  • Date/Time Types: DateTime, DateTime_NO_TZ, Date, Time, Time_NO_TZ
  • Other Basic Types: Boolean, JSON, JSONB, UUID, ENUM
  • Array Types: Array_Integer, Array_String, Array_Double, Array_Decimal, Array_DateTime, Array_DateTime_NO_TZ, Array_Date, Array_Time, Array_Time_NO_TZ, Array_UUID, Array_Boolean
  • Range Types: Range_Integer, Range_DateTime, Range_DateTime_NO_TZ, Range_Date, Range_Decimal, Range_Double, Range_Time, Range_Time_NO_TZ
  • PostGIS Types: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection, Geography
  • Computed Types: VIRTUAL

String Types

TypeDescriptionExample ValueConfiguration
StringVariable-length string (default 255)"Hello world"values.stringLength for custom length
TextUnlimited-length text"Long paragraph of text..."-
TEXTAlias for Text"Long paragraph of text..."-
CiTextCase-insensitive text (requires citext extension)"hello" matches "HELLO"-
TOKEN9-character unique string token"ABC123XYZ"Auto-generated

Numeric Types

TypeDescriptionExample ValueConfiguration
Integer32-bit signed integer42-
BigInt64-bit signed integer9007199254740991-
RealSingle-precision floating-point3.14-
DoubleDouble-precision floating-point3.141592653589793-
DOUBLEAlias for Double3.141592653589793-
DecimalArbitrary precision decimal123.45values.precision, values.scale

Date/Time Types

Timezone Pattern: Base types include timezone; append _NO_TZ for types without timezone.

TypePostgreSQL TypeDescriptionExample Value
DateTimetimestamp with time zoneTimestamp WITH timezone"2023-06-01T14:30:00Z"
DateTime_NO_TZtimestampTimestamp WITHOUT timezone"2023-06-01T14:30:00"
DatedateDate only (no time)"2023-06-01"
Timetime with time zoneTime WITH timezone"14:30:00+05:30"
Time_NO_TZtimeTime WITHOUT timezone"14:30:00"

Other Basic Types

TypeDescriptionExample Value
BooleanTrue/false valuetrue
JSONStandard JSON type{"key": "value"}
JSONBBinary JSON (more efficient){"key": "value"}
UUIDUniversally unique identifier"550e8400-e29b-41d4-a716-446655440000"
ENUMPredefined list of values"active" (stored as varchar)

Array Types (PostgreSQL Arrays)

For filtering array fields, see Complete Filter Reference - Array Operators.

TypeDescriptionExample Value
Array_IntegerArray of integers[1, 2, 3, 4, 5]
Array_StringArray of strings/text["red", "green", "blue"]
Array_DoubleArray of doubles[1.5, 2.7, 3.9]
Array_DecimalArray of decimals[10.50, 20.75, 30.25]
Array_DateTimeArray of timestamps WITH TZ["2023-01-01T00:00:00Z", ...]
Array_DateTime_NO_TZArray of timestamps WITHOUT TZ["2023-01-01T00:00:00", ...]
Array_DateArray of dates (date only)["2023-01-01", "2023-02-01"]
Array_TimeArray of times WITH TZ["14:30:00+05:30", ...]
Array_Time_NO_TZArray of times WITHOUT TZ["14:30:00", "15:45:00"]
Array_UUIDArray of UUIDs["uuid1", "uuid2"]
Array_BooleanArray of booleans[true, false, true]

Range Types (PostgreSQL Ranges)

Range types store lower/upper bounds with inclusivity flags. For filtering range fields, see Complete Filter Reference.

TypePostgreSQL TypeDescriptionExample Value
Range_Integerint4rangeInteger range{"lower": 1, "upper": 10}
Range_DateTimetstzrangeTimestamp range WITH timezone{"lower": "2023-01-01T00:00:00Z", ...}
Range_DateTime_NO_TZtsrangeTimestamp range WITHOUT timezone{"lower": "2023-01-01T00:00:00", ...}
Range_DatedaterangeDate range (date only){"lower": "2023-01-01", "upper": "2023-12-31"}
Range_DecimalnumrangeNumeric/decimal range{"lower": 10.5, "upper": 100.5}
Range_DoublenumrangeDouble precision range{"lower": 1.5, "upper": 99.9}
Range_TimetimetzrangeTime range WITH timezone{"lower": "09:00:00+05:30", ...}
Range_Time_NO_TZtimerangeTime range WITHOUT timezone{"lower": "09:00:00", "upper": "17:00:00"}

Range Value Structure:

{
  "lower": "value",           // Lower bound
  "upper": "value",           // Upper bound
  "lowerInclusive": true,     // Include lower bound (default: true)
  "upperInclusive": true      // Include upper bound (default: true)
}

PostGIS Geometry Types (requires PostGIS extension)

For geospatial filtering (within, contains, intersects, dwithin), see Complete Filter Reference - Geospatial Operators.

TypeDescriptionExample Value
PointSingle point in 2D space{"type": "Point", "coordinates": [lng, lat]}
LineStringLine in 2D space{"type": "LineString", "coordinates": [[lng1,lat1], [lng2,lat2]]}
PolygonPolygon in 2D space{"type": "Polygon", "coordinates": [[[lng1,lat1], ...]]}
MultiPointMultiple points{"type": "MultiPoint", "coordinates": [[lng1,lat1], ...]}
MultiLineStringMultiple line strings{"type": "MultiLineString", ...}
MultiPolygonMultiple polygons{"type": "MultiPolygon", ...}
GeometryCollectionCollection of mixed geometries{"type": "GeometryCollection", ...}
GeographyGeographic data (Earth spheroid)GeoJSON format

PostGIS Configuration: Use values.srid to set Spatial Reference System ID (default: 4326 for WGS84).

Computed/Virtual Types

TypeDescriptionConfiguration
VIRTUALComputed field with SQL expressionRequires calculated property with SQL expression

Virtual Field Example:

{
  "fullName": {
    "type": "VIRTUAL",
    "calculated": "CONCAT(\"firstName\", ' ', \"lastName\")"
  }
}

Field Type Examples

{
  "fields": {
    "id": {
      "type": "UUID",
      "primaryKey": true,
      "defaultValue": {
        "type": "UUIDV4"
      }
    },
    "name": {
      "type": "String",
      "allowNull": false,
      "length": 100
    },
    "description": {
      "type": "Text"
    },
    "price": {
      "type": "Decimal",
      "values": {
        "precision": 10,
        "scale": 2
      }
    },
    "status": {
      "type": "Enum",
      "values": ["draft", "published", "archived"],
      "defaultValue": "draft"
    },
    "tags": {
      "type": "Array",
      "itemType": "String"
    }
  }
}

Field Properties

Each field can have various properties that define its behavior:

PropertyTypeDescription
typestringThe data type of the field
allowNullbooleanWhether the field can be null (default: true)
uniquebooleanWhether the field must be unique (default: false)
primaryKeybooleanWhether the field is the primary key (default: false)
autoIncrementbooleanAuto-increment integer field (default: false)
defaultValuevariousDefault value if none is provided
valuesobject/arrayAdditional values for types like Enum or Decimal
lengthnumberMaximum length for String type
commentstringComment/description for the field
validateobjectValidation rules for the field
hiddenbooleanHide this field in API responses (default: false)
immutablebooleanField cannot be updated after creation (default: false)
descriptionstringHuman-readable description of the field

Validation Examples

{
  "fields": {
    "email": {
      "type": "String",
      "validate": {
        "isEmail": true,
        "notEmpty": true
      }
    },
    "age": {
      "type": "Integer",
      "validate": {
        "min": 18,
        "max": 99
      }
    },
    "website": {
      "type": "String",
      "validate": {
        "isUrl": true
      }
    },
    "zipCode": {
      "type": "String",
      "validate": {
        "matches": "^\\d{5}(-\\d{4})?$"
      }
    }
  }
}

Relationships

BAASIX supports the following relationship types:

One-to-Many (hasMany/belongsTo)

{
  "fields": {
    "id": {
      "type": "UUID",
      "primaryKey": true
    },
    "name": {
      "type": "String"
    },
    // Foreign key for the belongsTo relationship
    "category_id": {
      "type": "UUID",
      "allowNull": true
    },
    // Relationship definition
    "category": {
      "relType": "BelongsTo",
      "target": "categories",
      "foreignKey": "category_id",
      "as": "category",
      "onDelete": "SET NULL"
    },
    "products": {
      "relType": "HasMany",
      "target": "products",
      "foreignKey": "category_id",
      "as": "products"
    }
  }
}

Many-to-Many (belongsToMany)

{
  "fields": {
    "id": {
      "type": "UUID",
      "primaryKey": true
    },
    "name": {
      "type": "String"
    },
    "tags": {
      "relType": "BelongsToMany",
      "target": "tags",
      "through": "product_tags",
      "foreignKey": "product_id",
      "otherKey": "tag_id",
      "as": "tags"
    }
  }
}

One-to-One (hasOne/belongsTo)

{
  "fields": {
    "id": {
      "type": "UUID",
      "primaryKey": true
    },
    "user_id": {
      "type": "UUID",
      "allowNull": false,
      "unique": true
    },
    "user": {
      "relType": "BelongsTo",
      "target": "baasix_User",
      "foreignKey": "user_id",
      "as": "user"
    },
    "profile": {
      "relType": "HasOne",
      "target": "profiles",
      "foreignKey": "user_id",
      "as": "profile"
    }
  }
}

Relationship Properties

PropertyTypeDescription
relTypestringType of relationship (BelongsTo, HasMany, etc.)
targetstringTarget collection name
foreignKeystringForeign key field name
otherKeystringOther key in many-to-many relationships
throughstringJunction table for many-to-many relationships
asstringAlias for the relationship
onDeletestringAction on delete (CASCADE, SET NULL, etc.)
onUpdatestringAction on update (CASCADE, RESTRICT, etc.)

Schema Properties

Additional properties you can set at the schema level:

Timestamps

When timestamps: true is set, the following fields are automatically added:

{
  "createdAt": {
    "type": "DateTime",
    "allowNull": false
  },
  "updatedAt": {
    "type": "DateTime",
    "allowNull": false
  }
}

Paranoid (Soft Delete)

When paranoid: true is set, the following field is added:

{
  "deletedAt": {
    "type": "DateTime",
    "allowNull": true
  }
}

Records with a non-null deletedAt value are excluded from normal queries.

Indexing

Define indexes to optimize query performance:

{
  "schema": {
    "fields": {
      // Field definitions
    },
    "indexes": [
      {
        "name": "products_name_idx",
        "fields": ["name"]
      },
      {
        "name": "products_category_status_idx",
        "fields": ["category_id", "status"]
      },
      {
        "name": "products_price_idx",
        "fields": [["price", "DESC"]]
      },
      {
        "name": "products_description_fulltext",
        "type": "FULLTEXT",
        "fields": ["description"]
      },
      {
        "name": "products_created_at_idx",
        "method": "BTREE",
        "fields": ["createdAt"]
      },
      {
        "name": "products_location_geo_idx",
        "type": "SPATIAL",
        "fields": ["location"]
      }
    ]
  }
}

Index Properties

PropertyTypeDescription
namestringName of the index
fieldsarrayFields to index
typestringIndex type (BTREE, HASH, GIST, FULLTEXT, SPATIAL, etc.)
uniquebooleanWhether the index enforces uniqueness (default: false)
methodstringIndex method (database-specific)

Default Values

You can set default values for fields in multiple ways:

Static Default Value

{
  "status": {
    "type": "String",
    "defaultValue": "active"
  },
  "isVerified": {
    "type": "Boolean",
    "defaultValue": false
  },
  "score": {
    "type": "Integer",
    "defaultValue": 0
  }
}

Function Default Value

{
  "id": {
    "type": "UUID",
    "primaryKey": true,
    "defaultValue": {
      "type": "UUIDV4"
    }
  },
  "createdAt": {
    "type": "DateTime",
    "defaultValue": {
      "type": "NOW"
    }
  }
}

Supported Default Value Types

TypeDescription
NOWCurrent date and time
UUIDV4Version 4 UUID (random)
AUTOINCREMENTAuto-incrementing integer
SQLCustom SQL expression
SUIDShort unique ID

SQL Default Value Example:

{
  "sortOrder": {
    "type": "Integer",
    "defaultValue": {
      "type": "SQL",
      "value": "(SELECT COALESCE(MAX(sort_order), 0) + 1 FROM products)"
    }
  }
}

Examples

Complete Product Schema Example

{
  "collectionName": "products",
  "schema": {
    "name": "Product",
    "timestamps": true,
    "paranoid": true,
    "fields": {
      "id": {
        "type": "UUID",
        "primaryKey": true,
        "defaultValue": {
          "type": "UUIDV4"
        },
        "description": "Unique identifier for the product"
      },
      "name": {
        "type": "String",
        "allowNull": false,
        "length": 100,
        "validate": {
          "notEmpty": true
        },
        "description": "Product name"
      },
      "slug": {
        "type": "String",
        "unique": true,
        "allowNull": false,
        "description": "URL-friendly product identifier"
      },
      "description": {
        "type": "Text",
        "description": "Detailed product description"
      },
      "price": {
        "type": "Decimal",
        "allowNull": false,
        "values": {
          "precision": 10,
          "scale": 2
        },
        "validate": {
          "min": 0
        },
        "description": "Product price"
      },
      "status": {
        "type": "Enum",
        "values": ["draft", "active", "archived"],
        "defaultValue": "draft",
        "description": "Current product status"
      },
      "featured": {
        "type": "Boolean",
        "defaultValue": false,
        "description": "Whether the product is featured"
      },
      "inventory": {
        "type": "Integer",
        "defaultValue": 0,
        "validate": {
          "min": 0
        },
        "description": "Current inventory level"
      },
      "metadata": {
        "type": "JSON",
        "description": "Additional product metadata"
      },
      "tags": {
        "type": "Array",
        "itemType": "String",
        "description": "Product tags"
      },
      "category_id": {
        "type": "UUID",
        "allowNull": true,
        "description": "Foreign key for category"
      },
      "category": {
        "relType": "BelongsTo",
        "target": "categories",
        "foreignKey": "category_id",
        "as": "category",
        "onDelete": "SET NULL",
        "description": "Product category"
      },
      "images": {
        "relType": "HasMany",
        "target": "product_images",
        "foreignKey": "product_id",
        "as": "images",
        "description": "Product images"
      }
    },
    "indexes": [
      {
        "name": "products_name_idx",
        "fields": ["name"]
      },
      {
        "name": "products_status_featured_idx",
        "fields": ["status", "featured"]
      },
      {
        "name": "products_price_idx",
        "fields": [["price", "DESC"]]
      },
      {
        "name": "products_description_fulltext",
        "type": "FULLTEXT",
        "fields": ["description"]
      }
    ]
  }
}

User Authentication Schema Example

{
  "collectionName": "users",
  "schema": {
    "name": "User",
    "timestamps": true,
    "fields": {
      "id": {
        "type": "UUID",
        "primaryKey": true,
        "defaultValue": {
          "type": "UUIDV4"
        }
      },
      "email": {
        "type": "String",
        "allowNull": false,
        "unique": true,
        "validate": {
          "isEmail": true
        }
      },
      "password": {
        "type": "String",
        "allowNull": false,
        "hidden": true
      },
      "firstName": {
        "type": "String",
        "allowNull": false
      },
      "lastName": {
        "type": "String",
        "allowNull": false
      },
      "role_id": {
        "type": "UUID",
        "allowNull": false
      },
      "role": {
        "relType": "BelongsTo",
        "target": "baasix_Role",
        "foreignKey": "role_id",
        "as": "role"
      },
      "isActive": {
        "type": "Boolean",
        "defaultValue": true
      },
      "lastLogin": {
        "type": "DateTime",
        "allowNull": true
      },
      "profile": {
        "relType": "HasOne",
        "target": "user_profiles",
        "foreignKey": "user_id",
        "as": "profile"
      }
    }
  }
}

Best Practices

  1. Use UUID Primary Keys: UUIDs help prevent predictable IDs and are more suitable for distributed systems.
  2. Apply Proper Validation: Define validation rules to ensure data integrity.
  3. Include Descriptive Comments: Use the description field to document the purpose of each field.
  4. Consider Indexing Performance: Only create indexes for fields that are frequently queried.
  5. Use Relationships Properly: Define relationships to maintain data consistency and enable efficient querying.
  6. Implement Soft Deletes: Use the paranoid option for collections where data should be preserved even after deletion.
  7. Be Consistent with Naming: Follow a consistent naming pattern for fields and relationships.
  8. Set Default Values: Provide sensible defaults to ensure data consistency.
  9. Add Constraints: Use allowNull, unique, and validation rules to enforce data integrity.
  10. Design with Future Changes in Mind: Create flexible schemas that can accommodate future changes.

← Back to Documentation Home

On this page