FSL collection schema: Field definitions
Learn: Field definitions |
---|
Field definitions define fields for a collection’s documents.
You define field definitions as part of an FSL collection schema. Field definitions are part of a collection’s document type definition.
collection Order {
// Field definitions.
// Define the structure of the collection's documents.
description: String? // Equivalent to `status: String | Null`
customer: Ref<Customer>
status: "cart" | "processing" | "shipped" | "delivered"
createdAt: Time = Time.now()
...
}
You can create and manage schema using any of the following:
Fauna stores each collection schema as an FQL document in the
Collection
system collection. The Collection
document’s fields
field contains FQL
versions of the collection’s field definitions.
Name
- fieldName String Required
-
Document field name. A top-level field name 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> |
Yes |
Accepted data types for the field.
Separate multiple types by Types must be persistable. Use Use Document references for the following system collections are supported: References to named system collection documents are not supported. Use the Union type to enumerate accepted field values. See Enumerated field values. The Fields that accept Null are not guaranteed to exist in every document of the collection. |
|
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 reference as a default value. Document references for the following system collections are supported: References to named system collection documents are not supported. See Default to a document reference. You can’t use another field’s value as a default value. The default value is not applied if an explicit |
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: {
name: 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: {
name: String?
// Only accept ad hoc fields with `String` or `Int` values.
*: String | Int
}
}
Nested field migrations with wildcard constraints
You can’t run migrations on a nested field that has a neighboring wildcard constraint:
collection Product {
metadata: {
// The `metadata` object contains a wildcard constraint.
// You can't run migrations on `name` or other
// neighboring fields in `metadata`.
name: String?
*: Any
}
}
The add_wilcard
, remove_wildcard
, and move_wildcard
migration statements only
support top-level wildcard constraints, not nested wildcard constraints. These
statements let you safely handle conflicts between ad hoc and defined fields.
For an example, see Nested field migrations with wildcard constraints.
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 can’t run migrations on nested fields within an object Array. Otherwise, you define the object in the Array like 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
toString()
:
collection Product {
productId: String = newId().toString()
}
If used, Fauna generates a unique ID value for each document.
Default to a document reference
You can use a document reference as a default value:
collection Product {
// `category` defaults to a `Category` document reference
// 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 references for the following system collections are supported:
References to named system collection documents are not supported.
Document relationships
Use Ref<CollectionName>
to accept a
document reference as a data type:
collection Product {
// Accepts a reference to a `Category` collection
// document or `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.
Document references for the following system collections are supported:
References to named system collection documents are not supported.
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 fields 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
A top-level field name must be a valid identifier. A nested field name can be any valid string, including an identifier:
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"]
Defaults for nested fields
You can provide default values for fields in an object:
collection Customer {
address: {
// If `address.street` is not provided,
// use a default value of "unknown street".
street: String = "unknown street"
// If `address.city` is not provided,
// use a default value of "unknown city".
city: String = "unknown city"
state: String
postalCode: String
country: String
}
}
Default for an entire object
You can provide a default object for an object field. The default is used only if the entire object is omitted:
collection Customer {
// If no `address` object is provided, use the default object.
address: {
street: String
city: String
state: String?
postalCode: String?
country: String?
} = {
// The default object:
street: "unknown street",
city: "unknown city"
}
}
You can’t specify both a default object and nested field defaults.
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!