diff --git a/src/content/doc-surrealql/datamodel/futures.mdx b/src/content/doc-surrealql/datamodel/futures.mdx index de713dd1e..ef45d62ef 100644 --- a/src/content/doc-surrealql/datamodel/futures.mdx +++ b/src/content/doc-surrealql/datamodel/futures.mdx @@ -44,6 +44,34 @@ CREATE person SET ; ``` +## Futures inside schema definitions + +A future can be added to a schema definition as well. + +```surql +DEFINE FIELD accessed_at ON TABLE user VALUE { time::now() }; + +CREATE user:one; +SELECT * FROM ONLY user:one; +-- Sleep for one second +SLEEP 1s; +-- `accessed_at` is a different value now +SELECT * FROM ONLY user:one; +``` + +This differs from a non-future `VALUE` clause which is only calculated when it is modified (created or updated), but is not recalculated during a `SELECT` query which does not modify a record. + +```surql +DEFINE FIELD updated ON TABLE user VALUE time::now(); + +CREATE user:one; +SELECT * FROM ONLY user:one; +-- Sleep for one second +SLEEP 1s; +-- `updated` is still the same +SELECT * FROM ONLY user:one; +``` + ## Next steps You've now seen how to create dynamically computed properties on records, using either simple values, and values which depend on local and remote record fields. Take a look at the next chapter to understand how types can be cast and converted to other types. diff --git a/src/content/doc-surrealql/statements/define/field.mdx b/src/content/doc-surrealql/statements/define/field.mdx index e2a318a6f..3313541e5 100644 --- a/src/content/doc-surrealql/statements/define/field.mdx +++ b/src/content/doc-surrealql/statements/define/field.mdx @@ -41,6 +41,7 @@ The following expression shows the simplest way to use the `DEFINE FIELD` statem -- Declare the name of a field. DEFINE FIELD email ON TABLE user; ``` + ## Defining data types The `DEFINE FIELD` statement allows you to set the data type of a field. For a full list of supported data types, see [Data types](/docs/surrealql/datamodel). @@ -60,6 +61,44 @@ DEFINE FIELD locked ON TABLE user TYPE bool; DEFINE FIELD login_attempts ON TABLE user TYPE number; ``` +A `|` vertical bar can be used to allow a field to be one of a set of types. The following example shows a field that can be a [`UUID`](/docs/surrealql/datamodel/uuid) or an [`int`](/docs/surrealql/datamodel/numbers#integer-numbers), perhaps for `user` records that have varying data due to two diffent legacy ID types. + +```surql +-- Set a field to have either the uuid or int type +DEFINE FIELD user_id ON TABLE user TYPE uuid|int; +``` + +### Array type + +You can also set a field to have the array data type. The array data type can be used to store a list of values. You can also set the data type of the array's contents. + +```surql +-- Set a field to have the array data type +DEFINE FIELD roles ON TABLE user TYPE array; + +-- Set a field to have the array data type, equivalent to `array` +DEFINE FIELD posts ON TABLE user TYPE array; + +-- Set a field to have the array object data type +DEFINE FIELD emails ON TABLE user TYPE array; +``` + +### Making a field optional + +You can make a field optional by wrapping the inner type in an `option`, which allows you to store `NONE` values in the field. + +```surql +-- A user may enter a biography, but it is not required. +-- By using the option type you also allow for NONE values. +DEFINE FIELD biography ON TABLE user TYPE option; +``` + +The example below shows how to define a field `user` on a `POST` table. The field is of type [record](/docs/surrealql/datamodel/records). This means that the field can store a `record` or `NONE`. + +```surql +DEFINE FIELD user ON TABLE POST TYPE option>; +``` + ### Flexible data types Flexible types allow you to have `SCHEMALESS` functionality on a `SCHEMAFULL` table. This is necessary for working with nested `object` types, which by nature do not have defined fields. @@ -110,67 +149,79 @@ With `FLEXIBLE`, the output will be as expected as the schema now flexibly allow ] ``` -### Array type - -You can also set a field to have the array data type. The array data type can be used to store a list of values. You can also set the data type of the array's contents. +The fields of an object can be defined individually using the `.` operator. ```surql --- Set a field to have the array data type -DEFINE FIELD roles ON TABLE user TYPE array; --- A respective subfield for the array field will automatically be defined. --- If there are any existing definitions, clauses like VALUE and ASSERT will automatically be merged. -DEFINE FIELD roles.* ON TABLE user TYPE string; - --- Set a field to have the array data type, equavalent to `array` -DEFINE FIELD posts ON TABLE user TYPE array; --- The subfield will automatically be defined with the `any` data type, but we can overwrite it --- Set the contents of the array to only support a record data type -DEFINE FIELD posts.* ON TABLE user TYPE record; - --- Set a field to have the array object data type -DEFINE FIELD emails ON TABLE user TYPE array; -- Define nested object property types -DEFINE FIELD emails.*.address ON TABLE user TYPE string; -DEFINE FIELD emails.*.primary ON TABLE user TYPE bool; +DEFINE FIELD emails.address ON TABLE user TYPE string; +DEFINE FIELD emails.primary ON TABLE user TYPE bool; ``` -### Making a field optional -You can make a field optional by wrapping the inner type in an `option`, which allows you to store `NONE` values in the field. +### Using the `DEFAULT` clause to set a default value + +You can set a default value for a field using the `DEFAULT` clause. The default value will be used if no value is provided for the field. ```surql --- A user may enter a biography, but it is not required. --- By using the option type you also allow for NONE values. -DEFINE FIELD biography ON TABLE user TYPE option; +-- A user is not locked by default. +DEFINE FIELD locked ON TABLE user TYPE bool +-- Set a default value if empty +DEFAULT false; ``` -The example below shows how to define a field `user` on a `POST` table. The field is of type [record](/docs/surrealql/datamodel/records). This means that the field can store a `record` or `NONE`. +### Using the `VALUE` clause to set a field's value + +The `VALUE` clause differs from `DEFAULT` in that a default value is calculated if no other is indicated, otherwise accepting the value given in a query. ```surql -DEFINE FIELD user ON TABLE POST TYPE option>; -``` +DEFINE FIELD updated ON TABLE user DEFAULT time::now(); -### Setting a default value +-- Set `updated` to the year 1900 +CREATE user SET updated = d"1900-01-01"; +-- Then set to the year 1910 +UPDATE user SET updated = d"1910-01-01"; +``` -You can set a default value for a field using the `DEFAULT` clause. The default value will be used if no value is provided for the field. +A `VALUE` clause, on the other hand, will ignore attempts to set the field to any other value. ```surql --- A user is not locked by default. -DEFINE FIELD locked ON TABLE user TYPE bool --- Set a default value if empty -DEFAULT false; +DEFINE FIELD updated ON TABLE user VALUE time::now(); + +-- Ignores 1900 date, sets `updated` to current time +CREATE user SET updated = d"1900-01-01"; +-- Ignores again, updates to current time +UPDATE user SET updated = d"1900-01-01"; ``` -### `DEFAULT` inherited from `VALUE` +As the example above shows, a `VALUE` clause sets the value every time a record is modified (created or updated). However, the value will not be recalculated in a `SELECT` statement, which simply accesses the current set value. -If the `VALUE` clause contains a static query, meaning not depending on any variables, and in case no `DEFAULT` clause is specified, then the `VALUE` clause will be used as the `DEFAULT` clause as well. +```surql +DEFINE FIELD updated ON TABLE user VALUE time::now(); + +CREATE user:one; +SELECT * FROM ONLY user:one; +-- Sleep for one second +SLEEP 1s; +-- `updated` is still the same +SELECT * FROM ONLY user:one; +``` + +To create a field that is calculated each time it is accessed, a [`future`](/docs/surrealql/datamodel/futures) can be used. ```surql -DEFINE FIELD updated ON resource VALUE time::now(); +DEFINE FIELD accessed_at ON TABLE user VALUE { time::now() }; + +CREATE user:one; +SELECT * FROM ONLY user:one; +-- Sleep for one second +SLEEP 1s; +-- `accessed_at` is a different value now +SELECT * FROM ONLY user:one; ``` -### Alter a passed value +### Altering a passed value You can alter a passed value using the `VALUE` clause. This is useful for altering the value of a field before it is stored in the database. + In the example below, the `VALUE` clause is used to ensure that the email address is always stored in lowercase characters by using the [`string::lowercase`](/docs/surrealql/functions/database/string#stringlowercase) function. ```surql