|
| 1 | +from dataclasses import asdict, dataclass |
| 2 | +from textwrap import dedent |
| 3 | + |
| 4 | +from surrealdb import RecordID |
| 5 | + |
| 6 | +from kaig.db import DB |
| 7 | +from kaig.db.queries import WhereClause, order_limit_start |
| 8 | + |
| 9 | + |
| 10 | +@dataclass |
| 11 | +class User: |
| 12 | + id: str | None |
| 13 | + username: str |
| 14 | + team: RecordID | None = None |
| 15 | + |
| 16 | + |
| 17 | +def main(): |
| 18 | + table_user = "user" |
| 19 | + table_notification = "notification" |
| 20 | + tables = [table_user, table_notification] |
| 21 | + |
| 22 | + # -- DB connection |
| 23 | + url = "ws://localhost:8000/rpc" |
| 24 | + db_user = "root" |
| 25 | + db_pass = "root" |
| 26 | + db_ns = "kaig" |
| 27 | + db_db = "demo-simple" |
| 28 | + db = DB(url, db_user, db_pass, db_ns, db_db, tables=tables) |
| 29 | + |
| 30 | + # Remove this if you don't want to clear all your tables on every run |
| 31 | + db.clear() |
| 32 | + |
| 33 | + # Only required if you have vector_tables or graph_relations in your DB |
| 34 | + # db.init_db() |
| 35 | + |
| 36 | + # These are SurrealDB's RecordIDs. We don't necessarily need a `team` table |
| 37 | + # and records to use them |
| 38 | + team_green = RecordID("team", "green") |
| 39 | + team_blue = RecordID("team", "blue") |
| 40 | + |
| 41 | + # -- Define event |
| 42 | + query = f""" |
| 43 | + DEFINE EVENT create_user ON TABLE {table_user} |
| 44 | + WHEN $event = "CREATE" AND $after.team = None |
| 45 | + THEN ( |
| 46 | + CREATE {table_notification} SET |
| 47 | + msg = "User created without a team", |
| 48 | + user = $after.id, |
| 49 | + created_at = time::now() |
| 50 | + ); |
| 51 | + """ |
| 52 | + _ = db.sync_conn.query(query) |
| 53 | + |
| 54 | + # -- Create one record |
| 55 | + new_user = User(id=None, username="kaig", team=team_green) |
| 56 | + user = db.query_one( |
| 57 | + f"CREATE ONLY {table_user} CONTENT $record", |
| 58 | + {"record": asdict(new_user)}, |
| 59 | + User, |
| 60 | + ) |
| 61 | + print(f"\n--- Created: ---\n{user}") |
| 62 | + # User(id=RecordID(table_name=user, record_id=vv1gmrwwq6cvw45xg4wf), username='kaig', team=RecordID(table_name=team, record_id=green)) |
| 63 | + |
| 64 | + # Another way is using the DB connection object directly, which is the |
| 65 | + # SurrealDB Python SDK: https://surrealdb.com/docs/sdk/python |
| 66 | + # |
| 67 | + # doc = db.sync_conn.create(table, {"username": "kaig"}) |
| 68 | + |
| 69 | + # -- Create many records |
| 70 | + new_users = [ |
| 71 | + asdict(User(id=None, username="1", team=team_green)), |
| 72 | + asdict(User(id=None, username="2", team=team_blue)), |
| 73 | + asdict(User(id=None, username="3", team=team_blue)), |
| 74 | + asdict(User(id=None, username="4", team=None)), |
| 75 | + asdict(User(id=None, username="5", team=None)), |
| 76 | + ] |
| 77 | + _ = db.query(f"INSERT INTO {table_user} $list", {"list": new_users}, User) |
| 78 | + |
| 79 | + # -- Query all documents |
| 80 | + users = db.query(f"SELECT * FROM {table_user}", {}, User) |
| 81 | + print(f"\n--- All: --\n{users}") |
| 82 | + # [User(id=RecordID(table_name=user, record_id=25sslmmrv4p4rm4vpbw0), username='5', team=None), User(id=RecordID(table_name=user, record_id=8nbpgmkw9u438lx3g47r), username='1', team=RecordID(table_name=team, record_id=green)), User(id=RecordID(table_name=user, record_id=ifrfajan8c44cn7vjz09), username='3', team=RecordID(table_name=team, record_id=blue)), User(id=RecordID(table_name=user, record_id=rcycrch7qie3ytgd1giy), username='2', team=RecordID(table_name=team, record_id=blue)), User(id=RecordID(table_name=user, record_id=sa39vpybhmt7h4r405hb), username='4', team=None), User(id=RecordID(table_name=user, record_id=vv1gmrwwq6cvw45xg4wf), username='kaig', team=RecordID(table_name=team, record_id=green))] |
| 83 | + |
| 84 | + # -- Query one document |
| 85 | + assert user is not None |
| 86 | + result = db.query_one( |
| 87 | + "SELECT * FROM ONLY $record", {"record": user.id}, User |
| 88 | + ) |
| 89 | + print(f"\n--- Query one: ---\n{result}") |
| 90 | + # User(id=RecordID(table_name=user, record_id=vv1gmrwwq6cvw45xg4wf), username='kaig', team=RecordID(table_name=team, record_id=green)) |
| 91 | + |
| 92 | + # -- With filters, sort, and pagination |
| 93 | + where = WhereClause() |
| 94 | + where = where.and_("team", team_green) |
| 95 | + where_clause, where_vars = where.build() |
| 96 | + order_limit_start_clause = order_limit_start("username", "DESC", 5, 0) |
| 97 | + query = dedent(f""" |
| 98 | + SELECT * |
| 99 | + FROM {table_user} |
| 100 | + {where_clause} |
| 101 | + {order_limit_start_clause} |
| 102 | + """) |
| 103 | + filtered = db.query(query, where_vars, User) |
| 104 | + print(f"\n--- Filtered: --\n{filtered}") |
| 105 | + # [User(id=RecordID(table_name=user, record_id=vv1gmrwwq6cvw45xg4wf), username='kaig', team=RecordID(table_name=team, record_id=green)), User(id=RecordID(table_name=user, record_id=8nbpgmkw9u438lx3g47r), username='1', team=RecordID(table_name=team, record_id=green))] |
| 106 | + |
| 107 | + count = db.count(table_user, "", {}) |
| 108 | + print(f"\n--- Total user count: {count}") |
| 109 | + |
| 110 | + # -- Query notifications |
| 111 | + notifications = db.query(f"SELECT * FROM {table_notification}", {}, dict) |
| 112 | + print(f"\n--- Notifications: --\n{notifications}") |
| 113 | + # [{'created_at': datetime.datetime(2025, 9, 24, 22, 3, 58, 899922, tzinfo=datetime.timezone.utc), 'id': RecordID(table_name=notification, record_id=gj1hpep0n8dflso4pt78), 'msg': 'User created without team', 'user': RecordID(table_name=user, record_id=sa39vpybhmt7h4r405hb)}, {'created_at': datetime.datetime(2025, 9, 24, 22, 3, 58, 899955, tzinfo=datetime.timezone.utc), 'id': RecordID(table_name=notification, record_id=i45i8n9t4qww5r9zswzp), 'msg': 'User created without team', 'user': RecordID(table_name=user, record_id=25sslmmrv4p4rm4vpbw0)}] |
| 114 | + |
| 115 | + |
| 116 | +if __name__ == "__main__": |
| 117 | + main() |
0 commit comments