Each of the types mentioned in the data model is a subset of an all-encompassing type called a value.
Comparing and ordering values
While it is unsurprising that a data type can be compared with itself, it may be surprising that different types can also be compared with each other.
9 > 1; // Returns true
[] > time::now(); // Also returns trueThis comparison is possible because every type in SurrealDB is a subset of value, and a comparison of any type with another is also simply a comparison of a value with another value. The order of values from least to greatest is:
nonenullboolnumberstringdurationdatetimeuuidarraysetobjectgeometrybytestablerecordfileregexrange
As a result, all of the following return true.
[
null > none,
true > null,
1 > true,
'a' > 999999999,
1m > 'a',
time::now() > 1m,
rand::uuid() > time::now(),
[ 9, 10 ] > rand::uuid(),
{ 9, 10 } > [ 9, 10 ],
{} > { 9, 10 },
(9.9, 9.9) > {},
<bytes>"Aeon" > (9.9, 9.9),
type::table("person") > <bytes>"Aeon",
person:one > type::table("person"),
f"file://myfile.txt" > person:one,
<regex>"a|b" > f"file://myfile.txt",
0..10 > <regex>"a|b",
|| > 0.. 10
];Being able to compare a value with any other value is what makes SurrealDB's record range syntax possible.
CREATE time_data:[d'2024-07-23T00:00:00.000Z'];
CREATE time_data:[d'2024-07-24T00:00:00.000Z'];
CREATE time_data:[d'2024-07-25T00:00:00.000Z'];
-- Records from the 24th to the 25th
SELECT * FROM time_data:[d'2024-07-24']..[d'2024-07-25'];
-- Records from the 24th
SELECT * FROM time_data:[d'2024-07-24']..;
-- All records
SELECT * FROM time_data:[NONE]..;The .. open-range syntax also represents an infinite value inside a record range query, making it the greatest possible value and the inverse of NONE, the lowest possible value. A part of a record range query that begins with NONE and ends with .. will thus filter out nothing.
CREATE temperature:['London', d'2025-02-19T00:00:00.000Z'] SET val = 5.5;
CREATE temperature:['London', d'2025-02-20T00:00:00.000Z'] SET val = 5.7;
-- Return all records as long as index 0 = 'London'
SELECT * FROM temperature:['London', NONE]..=['London', ..];[
{
id: temperature:[
'London',
d'2025-02-19T00:00:00Z'
],
val: 5.5f
},
{
id: temperature:[
'London',
d'2025-02-20T00:00:00Z'
],
val: 5.7f
}
]Inside a schema, the keyword any is used to denote any possible value.
DEFINE FIELD anything ON TABLE person TYPE any;Values and truthiness
Any value is considered to be truthy if it is not NONE, NULL, or a default value for the data type. A data type at its default value is one that is empty, such as an empty string or array or object, or a number set to 0.
The following example shows the result of the array::all() method, which checks to see if all of the items inside an array are truthy or not.
array::all(["", 1, 2, 3]); // false because of ""
array::all([{}, 1, 2, 3]); // false because of {}
array::all(["SurrealDB", { is_nice_database: true }, 1, 2, 3]); // trueAs the ! operator reverses the truthiness of a value, a doubling of this operator can also be used to check for truthiness.
[
!!"Has a value", !!"", // true, false
!!true, !!false, // true, false
!!{ is_nice_database: true }, !!{} // true, false
];Nesting depth
Available since: v3.3.0
A value can be nested at most 256 levels deep. Each array, set, object and range adds a level, and so does the key of a record ID, so a compound ID such as t:[[1]] counts towards the same limit. The limit is fixed and cannot be configured.
A write that would store a deeper value fails with The value is nested too deeply, whether the value arrives in one statement or grows one level at a time through repeated updates. A deeper value that is already stored returns the same error when it is read. The parsing depth limits are separate: they bound how deeply a query or a message may nest, while this limit applies to the value itself.
CREATE deep:1 SET v = 1;
-- Wrap the value in one more array on each pass
FOR $i IN 1..300 {
UPDATE deep:1 SET v = [v];
};'The value is nested too deeply. A value may be nested at most 256 levels; reduce the nesting or split the data across records'