Field definitions

Learn: Schema

Field definitions and schema migrations are in beta.

A schema migration is required to change a collection’s field definitions or wildcard constraint. By performing a schema migration, you automatically opt-in to the beta.

To register for the beta and sign up for production support, go to https://go.fauna.com/schemabetaproductionsupport.

Field definitions define fields for a collection’s documents.

Field definitions are part of a collection’s document type definition. You include field definitions in a collection schema.

collection Order {
  description: String? // Equivalent to `status: String | Null`
  customer: Ref<Customer>
  status: "cart" | "processing" | "shipped" | "delivered"
  createdAt: Time = Time.now()
  ...
}

Syntax

<fieldName>: <types>[ = <defaultValue>]

Name

fieldName String Required

Document field name. Top-level field names must be a valid identifier.

Use a top-level wildcard (*) constraint to specify accepted data types for ad hoc fields. See Wildcard constraints.

Properties

Property Type Required Description

<types>

String

Yes

Accepted data types for the field. Separate multiple types by |.

Types must be persistable. Use Any to accept any persistable value. Use Ref<CollectionName> to accept a collection’s documents as a data type. Use the Union type to enumerate accepted field values. See Enumerated field values.

The ? (nullable) type annotation indicates the field accepts Null values. ? is equivalent to | Null.

Fields that accept Null are not guaranteed to exist in every document of the collection.

<defaultValue>

String

Default field value. Used when the field is missing during document creation or replacement.

Can be an FQL expression. The expression can have no effect other than to:

Fauna evaluates the expression at write time.

You can use a document as a default value. See Default to a document.

The default value is not applied if an explicit null value is provided or during document updates.

Wildcard constraints

When you add field definitions to a collection, the collection’s documents can only contain the defined fields. To accept arbitrary ad hoc fields, add a wildcard (*) constraint:

collection Order {
  status: String?

  // Wildcard constraint.
  // Allows arbitrary ad hoc fields.
  *: Any
}

A wildcard constraint is part of a collection’s document type definition. You can’t specify a default value for a wildcard constraint.

A collection can only have one top-level wildcard constraint. If present, the top-level wildcard constraint’s definition must be *: Any.

Schemaless by default

If a collection has no field definitions, it implicitly accepts ad hoc fields of any type. This is equivalent to:

collection Order {
  // Contains no field definitions
  *: Any
}

This means the collection is schemaless. The collection’s documents can contain any field.

Permissive document type

If a collection has both field definitions and a wildcard constraint, it has a permissive document type. The collection’s documents can contain ad hoc fields. However, fields must conform to the structure of their definitions.

collection Order {
  // Contains field definitions and a wildcard constraint
  status: String?
  *: Any
}

Strict document type

If a collection has field definitions but doesn’t have a wildcard constraint, it does not accept documents with ad hoc fields. This is called a strict document type.

collection Order {
  // Contains no wildcard constraint
  status: String?
}

Nested wildcard constraints

You can include a wildcard constraint in an object field definition to accept ad hoc fields in the object:

collection Product {
  metadata: {
    internalDesc: String?
    // The `metadata` object can contain ad hoc fields
    // of any type.
    *: Any
  }
}

You can restrict the accepted data types of ad hoc fields in the object:

collection Product {
  metadata: {
    // Only accept ad hoc fields with `String` or `Int` values
    *: String | Int
  }
}

Document TTLs default

The document_ttls field to controls whether you can write to the ttl field for collection documents.

If a collection schema contains field definitions, the schema’s document_ttls field defaults to false. Otherwise, document_ttls defaults to true.

See Enable or disable ttl writes

Examples

Arrays

Use Array<…​> to accept Array values:

collection Product {
  categories: Array<String>
}

To accept an object array:

collection Customer {
  addresses: Array<{
    street: String
    city: String
    state: String
    zipCode: String
  }>
}

You define the object in the array the same way as an object field. See Objects.

Default to today’s date

Use Date.today() to set today’s date as a default value:

collection Product {
  creationDate: Date = Date.today()
}

Fauna evaluates the expression at write time.

Default to the current time

Use Time.now() to set the current time as a default value:

collection Product {
  creationTime: Time = Time.now()
}

Fauna evaluates the expression at write time.

Default to a unique ID

Use newId() to use a unique ID as the default value. You must cast the ID to a String using string.toString():

collection Product {
  productId: String = newId().toString()
}

If used, Fauna generates a unique ID value for each document.

Default to a document

You can use a document as a default value:

collection Product {
  // Default `category` to a `Category` collection document.
  // Replace `400684606016192545` with a `Category` document ID.
  category: Ref<Category> = Category("400684606016192545")
}

Fauna doesn’t guarantee the document exists. You can’t fetch the document using an FQL expression.

Document relationships

Use Ref<CollectionName> to accept a document reference as a data type:

collection Product {
  // Accepts `Category` collection documents and `null`.
  category: Ref<Category>?
}

Documents may contain references to documents that don’t exist. These are called dangling references.

You can’t delete a collection that’s referenced by a field definition. See Drop a document reference field.

Enumerated field values

To accept enumerated values:

collection Customer {
  status: "silver" | "gold" | "platinum"?
}

Objects

To define a field containing an object:

collection Customer {
  // `address` is an object.
  address: {
    // `street` and the other fields are
    // nested in the `address` object.
    street: String
    city: String
    state: String
    postalCode: String
    country: String
  }
}

You can nest objects within other objects:

collection Customer {
  address: {
    street: String
    city: String
    state: String
    postalCode: String
    country: {
      // `countryCode` is nested in the
      // `country` field. The `country`
      // field is nested in the `address` field.
      countryCode:
    }
  }
}

Delimit nested fields

You can use commas to optionally delimit an object’s nested fields:

collection Customer {
  address: {
    street: String,
    city: String,
    state: String,
    postalCode: String,
    country: String
  }
}

Nested field names

Top-level field names must be a valid identifier. Nested field names can be any valid string:

collection Product {
  // `metadata` is a top-level field name and must be an identifier.
  metadata: {
    // `internal description` is a nested field name.
    // The name contains a space and is not a valid
    // identifier.
    "internal description": String
  }
}

You can access non-identifier field names using bracket notation:

// Create a `Product` document using the previous schema.
let product = Product.create({
  metadata: {
    "internal description": "Fresh key limes"
  }
})

// Access the document's nested `internal description`
// field using bracket notation.
product.metadata["internal description"]

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!