Before version 3.0.0, sets were simply arrays that deduplicated their items. To emulate the former behaviour, add the clause VALUE $value.distinct() to a DEFINE FIELD definition.
A set is similar to an array, but with two key differences:
The values in a set are automatically deduplicated.
The values in a set are automatically ordered.
Set syntax and casting
A set can be created using the literal syntax {}.
/**[test]
[[test.results]]
value = "{1, 2, 6}"
*/
RETURN {1, 6, 6, 2};
-- {1, 2, 6}To create a set with zero items or a single item, add a comma.
/**[test]
[[test.results]]
value = "true"
[[test.results]]
value = "true"
[[test.results]]
value = "false"
[[test.results]]
value = "false"
*/
{,}.is_set(); -- true
{9,}.is_set(); -- true
{}.is_set(); -- false
{9}.is_set(); -- falseIn addition to the {} literal syntax, an array can be cast into a set.
/**[test]
[[test.results]]
value = "NONE"
[[test.results]]
value = "NONE"
[[test.results]]
value = "[{ bank_accounts: [55555, 55555, 98787], id: customer:jud5qdgtehj5z1cv91e1, languages: {'en', 'ja', 'kr'} }]"
skip-record-id-key = true
*/
DEFINE FIELD bank_accounts ON TABLE customer TYPE array<int>;
DEFINE FIELD languages ON TABLE customer TYPE set<string>;
CREATE customer SET
bank_accounts = [
55555,
55555,
98787
],
languages = <set>[
"en",
"ja",
"kr",
"kr"
];[
{
bank_accounts: [
55555,
98787
],
id: customer:uv6mn62t8td9vzvfogh4,
languages: {
'en',
'ja',
'kr'
}
}
]Casting into a set and back into an array can be a convenient way to deduplicate items in the same way that the array::distinct() and array::sort() functions are used.
/**[test]
[[test.results]]
value = "[3, 4, 5, 6, 7, 9, 18]"
[[test.results]]
value = "[3, 4, 5, 6, 7, 9, 18]"
*/
<array><set>[18,7,6,6,6,6,5,4,3,9];
[18,7,6,6,6,6,5,4,3,9].distinct().sort();[3, 4, 5, 6, 7, 9, 18]Using the index operator on sets
The [] index operator can be used on a set in the same manner as an array. Note however that due to a set's automatic ordering, its individual values are technically not assigned an index. This can be seen in the following example in which [0] for an array will return whichever item happens to be at that location, while for a set [0] will automatically be the item with the least value.
To return the greatest value of a set, use [$] (since 3.2.0) or the set::last() function.
/**[test]
[[test.results]]
value = "4"
[[test.results]]
value = "2"
[[test.results]]
value = "6"
[[test.results]]
value = "6"
*/
-- Array: returns 4 at index 0
[4,6,2][0];
-- Set: returns 2, the least item
(<set>{4,6,2})[0];
-- Set: returns 6, the greatest item
{4,6,2}[$];
{4,6,2}.last();Filtering and mapping with set functions
SurrealDB also includes a number of methods for sets that make it easier to filter and map. These methods take a closure (an anonymous function) that works in a similar way to the $this parameter above.
Here is an example of the set::filter() method being used. Note that the parameter name inside the closure is named by the user, so $val in the example below could be $v or $some_val or anything else.
/**[test]
[[test.results]]
value = "{3, 5}"
*/
{1,3,5}.filter(|$val| $val > 2);
-- {3,5}Adding sets
An set can be added to another set or array, resulting in a single set consisting of the items of the first followed by those of the second.
/**[test]
[[test.results]]
value = "{1, 2, 3, 4}"
[[test.results]]
value = "{1, 2, 3, 4}"
*/
{1,2} + [3,4];
{1,2} + {3,4};{1,2,3,4}