Each of the types mentioned in the data model is a subset of an all-encompassing type called a value.
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.
RETURN 9 > 1; // Returns true RETURN [] > time::now(); // Also returns true
This 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:
none
null
bool
number
string
duration
datetime
UUID
array
object
geometry
bytes
record
As a result, all of the following return true
.
RETURN [ null > none, true > null, 1 > true, 'a' > 999999999, 1s > 'a', time::now() > 1s, rand::uuid() > time::now(), [] > rand::uuid(), {} > [], (89.0, 89.0) > {}, <bytes>'Aeon' > (89.0, 89.0), person:aeon > <bytes>'Aeon' ];
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', ..];
Output[ { id: temperature:[ 'London', d'2025-02-19T00:00:00Z' ], val: 5.5f }, { id: temperature:[ 'London', d'2025-02-20T00:00:00Z' ], val: 5.7f } ]
Here is the same NONE
to ..
pattern used in an object-based record ID for the same weathe rdata.
CREATE temperature:{ city: 'London', time: d'2025-02-19T00:00:00.000Z' } SET val = 5.5; CREATE temperature:{ city: 'London', time: d'2025-02-20T00:00:00.000Z' } SET val = 5.7; SELECT * FROM temperature:{ city: 'London', time: NONE }..{ city: 'London', time: .. };
Output[ { id: temperature:{ city: 'London', time: d'2025-02-19T00:00:00Z' }, val: 5.5f }, { id: temperature:{ city: 'London', time: 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;
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.
RETURN array::all(["", 1, 2, 3]); // false because of "" RETURN array::all([{}, 1, 2, 3]); // false because of {} RETURN array::all(["SurrealDB", { is_nice_database: true }, 1, 2, 3]); // true
As the ! operator reverses the truthiness of a value, a doubling of this operator can also be used to check for truthiness.
RETURN [ !!"Has a value", !!"", // true, false !!true, !!false, // true, false !!{ is_nice_database: true }, !!{} // true, false ];