14-surrealdbTermsLevel_04option<T (Optional Fields)

option<T> (Optional Fields)

Level 4 — Schema Definition & Constraints The type wrapper in SurrealDB used inside field definitions to mark a property as optional, allowing it to be omitted (evaluating to NONE) without triggering schema validation errors in SCHEMAFULL tables.


1. Prerequisites


2. Term Category

Data Type (optional field type wrapper): - Database Structure / Paradigm


3. Explanation

(1) Design Motivation — "Why did we design this?"

In standard SQL databases (PostgreSQL), all columns exist on every row:

  • If you want a column to be optional, you mark it as NULL.
  • The column space is still reserved, and it defaults to NULL.

In schema-full NoSQL collections, you need a way to declare that a field can be completely absent from the JSON record on disk (evaluating to NONE):

  • If you define a field simply as TYPE string in a SCHEMAFULL table, SurrealDB expects that field to be provided on every write.
  • If you omit it, the validation parser blocks the transaction, treating it as a missing required parameter.

We designed the option<T> type wrapper to define optional schema properties.

By wrapping a type (e.g. option<string> or option<int>), you instruct SurrealDB that the field is optional.

If the application inserts a record and omits this field, SurrealDB accepts the write, and the property is stored as absent (NONE) on disk, optimizing storage space.


(2) Required vs. Optional Syntax

  • Required Field: DEFINE FIELD email ON user TYPE string;
    • Rule: Must be provided on inserts. Cannot be NONE.
  • Optional Field: DEFINE FIELD phone ON user TYPE option<string>;
    • Rule: Can be omitted on inserts. Defaults to NONE.

(3) Reality Metaphor (Questionnaire Boxes)

Imagine filling out a customer profile paper form:

  • Required Field (No Option Wrapper): A box labeled "First Name (Required)".
    • If you leave the box blank, the clerk flags the application, rejects the form, and halts the line.
  • Optional Field (option<T>): A box labeled "Middle Name (Optional)".
    • You can leave the box completely blank.
    • The clerk accepts the form anyway, and the box contains no data.

(4) Code Examples

Creating Optional Fields in SurrealQL

Let's model a member settings schema:

DEFINE TABLE member SCHEMAFULL;

-- 1. Required fields (must be provided on insert)
DEFINE FIELD username ON member TYPE string;
DEFINE FIELD email ON member TYPE string;

-- 2. Optional fields (wrapped in option<T>)
DEFINE FIELD middle_name ON member TYPE option<string>;
DEFINE FIELD referral_code ON member TYPE option<string>;

-- This write SUCCEEDS (middle_name and referral_code are omitted):
CREATE member:alice SET
  username = "alice_dev",
  email = "alice@example.com";

-- This write FAILS (email is required but missing!):
CREATE member:bob SET
  username = "bob_dev";
-- Error: "Database validation error: Field 'email' is required..."

4. Common Mistakes & Pitfalls

Mistake 1: Defining fields that users frequently skip (like 'avatar_url' or 'bio') as standard types without the 'option' wrapper, blocking account creation

The mistake: Running DEFINE FIELD bio ON user TYPE string; in a SCHEMAFULL signup table, and noticing that registrations fail when users leave the biography field blank.

Why it's wrong: Without option<T>, the type string is strictly required.

If a signup query does not include bio, SurrealDB blocks the write, breaking your user onboarding flow.

Fix: Always wrap profile fields that users can skip in option<T> to make them optional:

-- CORRECT
DEFINE FIELD bio ON user TYPE option<string>;

Mistake 2: Defining Mandatory Non-Null Fields as TYPE option<T>

The mistake: Defining DEFINE FIELD email ON TABLE user TYPE option<string>; when email is required.

Why it's wrong: option<T> explicitly permits the field to be NONE (absent). If the field is mandatory, use TYPE string.

Incorrect:

DEFINE FIELD required_email ON TABLE user TYPE option<string>; // Allows NONE!

Fix:

DEFINE FIELD required_email ON TABLE user TYPE string; // Strictly required string

Mistake 3: Expecting option<T> to Accept Incompatible Types

The mistake: Inserting number 123 into TYPE option<string> field.

Why it's wrong: option<T> accepts NONE OR type T (string). It rejects other incompatible data types.

Incorrect:

DEFINE FIELD bio ON TABLE user TYPE option<string>;
CREATE user SET bio = 123; // ❌ Type error: Expected option<string>, got number

Fix:

CREATE user SET bio = "Dev bio"; // Valid string or omit field for NONE

5. Practice Exercises

Exercise 1: Defining Optional Fields with option<T>

Scenario: A user profile schema requires a mandatory username string and an optional middle_name string (option<string>).

Requirements:

  1. Define table user as SCHEMAFULL.
  2. Define field username as string.
  3. Define field middle_name as option<string>.
Answer

Implementation

DEFINE TABLE user SCHEMAFULL;
DEFINE FIELD username ON TABLE user TYPE string;
DEFINE FIELD middle_name ON TABLE user TYPE option<string>;

CREATE user:u1 SET username = "jdoe";

Technical Explanation

  1. option<T> designates a field as optional, permitting NONE or NULL values.
  2. In SCHEMAFULL mode, non-option fields require explicit values during creation.
  3. Replaces SQL NULLABLE column designations.

Scenario: Define an optional manager link pointer option<record<user>> on table employee.

Requirements:

  1. Define field manager on table employee as option<record<user>>.
Answer

Implementation

DEFINE TABLE employee SCHEMAFULL;
DEFINE FIELD manager ON TABLE employee TYPE option<record<user>>;

CREATE employee:e1 SET name = "CEO"; -- Manager is NONE

Technical Explanation

  1. option<record<table>> allows optional foreign record link pointers.
  2. Permits top-level entities (like a CEO) to omit manager pointers cleanly.
  3. Enables flexible relational modeling.

Exercise 3: Querying Optional Fields with NONE Checks

Scenario: Query employees who do not have an assigned manager (manager = NONE).

Requirements:

  1. Write a SELECT query filtering WHERE manager = NONE.
Answer

Implementation

SELECT * FROM employee WHERE manager = NONE;

Technical Explanation

  1. WHERE field = NONE checks for omitted optional fields.
  2. Distinguishes missing optional fields from set values.
  3. Evaluates optional field presence in table scans.


7. Key Takeaways

  • option<T> marks a field as optional in SCHEMAFULL tables.
  • Equivalent to setting a column as nullable in SQL.
  • Allows fields to be omitted from write payloads, evaluating to NONE.
  • Required fields (not wrapped in option<T>) throw errors if missing on write.
  • Prevents database signup crashes on skipped user profile fields.
  • Optimizes storage by omitting absent keys from binary blocks on disk.
  • Wrap nested types inside options (e.g. option<array<string>>).
Built with LogoFlowershow