A SurrealDB set holds each value once, in an order that the server chooses, and it can hold any value, including objects and arrays. The Python SDK reads every set as a SurrealSet, a list subclass that the SDK sends back as a set. This page documents how sets convert, and what to check when you write back a record that holds a set. The set type needs SurrealDB 3.0 or later.
from surrealdb import SurrealSetSource: set.py
How sets convert
| Python | SurrealDB | Read back as |
|---|---|---|
set, frozenset | set | SurrealSet |
SurrealSet | set | SurrealSet |
list, tuple | array | list |
A Python set can only hold hashable values. To send a set that holds objects or arrays, use a SurrealSet.
Constructor
SurrealSet(iterable=())Parameter | Type | Description |
|---|---|---|
iterable | Iterable | The members, as for list(). Defaults to an empty set. |
A SurrealSet that you build does not remove duplicates or sort its members. The server does that when it receives the set, and a set always reads back in the server's order.
from surrealdb import Surreal, SurrealSet
with Surreal("ws://localhost:8000") as db:
db.signin({"username": "root", "password": "secret"})
db.use("surrealdb", "docs")
tags = SurrealSet(["news", "intro", "news"])
print(db.query("RETURN $tags", {"tags": tags}).first())
print(db.query("RETURN $tags", {"tags": {3, 1, 2}}).first())SurrealSet(['intro', 'news'])
SurrealSet([1, 2, 3]) Working with a SurrealSet
A SurrealSet is a list, so you can index it, iterate over it, take its len() and test membership with in. It is equal to a list that holds the same members in the same order, and, as with any list, the order counts.
tags = SurrealSet(["intro", "news"])
print(tags == ["intro", "news"], tags == ["news", "intro"])
print(tags[0], len(tags), "news" in tags)True False
intro 2 TrueWriting a set back
A set field reads as a SurrealSet, so a record that you read and write back keeps the field as a set. A list is sent as an array. On a schemaless table, writing a list over a set field turns the field into an array, which keeps duplicates from then on. A schemafull field of type set<T> converts the array back to a set.
from surrealdb import RecordID, Surreal
with Surreal("ws://localhost:8000") as db:
db.signin({"username": "root", "password": "secret"})
db.use("surrealdb", "docs")
post = RecordID("post", 1)
db.create(post, {"tags": {"news", "intro"}})
sql = "RETURN type::of($post.tags)"
record = db.select(post).execute()
db.update(post, record)
print(db.query(sql, {"post": post}).first())
db.update(post, {"tags": ["news", "intro"]})
print(db.query(sql, {"post": post}).first())set
arraySurrealDB 2.x
SurrealDB 2.x has no set type. It refuses a set, frozenset or SurrealSet with an error that asks for a list, and its <set> cast gives an array, which reads back as a list. Send a list to a SurrealDB 2.x server.
Pydantic models
A pydantic field typed as list[...] turns a SurrealSet into a plain list. A field typed as SurrealSet keeps it, with arbitrary_types_allowed=True on the model, but model_dump() still gives a plain list. Before you write such data back, wrap the value again, for example data["tags"] = SurrealSet(data["tags"]).
See also
Python values for every value class
Value types for how every value converts
Sets in SurrealQL