Go Client
Official SDK
v0.1.0
Go 1.18+
Getting Started
Installation
go get github.com/solisoft/solidb-go-client
Requirements: Go 1.18 or higher. The client uses msgpack/v5 for binary serialization.
Quick Start
package main
import (
"fmt"
"github.com/solisoft/solidb-go-client/solidb"
)
func main() {
// Create client instance
client := solidb.NewClient("127.0.0.1", 6745)
// Establish connection
if err := client.Connect(); err != nil {
panic(err)
}
defer client.Close()
// Authenticate
if err := client.Auth("_system", "admin", "password"); err != nil {
panic(err)
}
// Set database context (required for sub-clients)
client.UseDatabase("mydb")
// Basic CRUD operations
doc, _ := client.Insert("mydb", "users", map[string]interface{}{
"name": "Alice",
"age": 30,
}, nil)
fmt.Println("Created:", doc["_key"])
user, _ := client.Get("mydb", "users", doc["_key"].(string))
fmt.Println("Retrieved:", user["name"])
client.Update("mydb", "users", doc["_key"].(string), map[string]interface{}{
"age": 31,
}, true)
// Query with SDBQL
results, _ := client.Query("mydb", "FOR u IN users FILTER u.age > @min RETURN u",
map[string]interface{}{"min": 25})
fmt.Printf("Found %d users\n", len(results))
// Use management sub-clients
scripts, _ := client.Scripts().List()
triggers, _ := client.Triggers().List()
fmt.Printf("Scripts: %d, Triggers: %d\n", len(scripts), len(triggers))
}
Connection Management
// Initialize with host and port
client := solidb.NewClient("127.0.0.1", 6745)
// Connect (establishes TCP socket with magic header handshake)
err := client.Connect()
if err != nil {
log.Fatal("Connection failed:", err)
}
// Check connection health
err = client.Ping()
if err != nil {
log.Println("Connection unhealthy:", err)
}
// Close connection when done
client.Close()
| Method | Returns | Description |
|---|---|---|
NewClient(host, port) | *Client | Create client instance |
Connect() | error | Establish TCP connection |
Ping() | error | Check connection health |
Close() | error | Close connection |
UseDatabase(name) | *Client | Set database context for sub-clients |
Authentication
// Authenticate with database, username, and password
err := client.Auth("_system", "admin", "password")
if err != nil {
log.Fatal("Authentication failed:", err)
}
// Authentication is required for most operations
// The session remains authenticated until disconnected
Core Operations
Database Operations
// List all databases
databases, err := client.ListDatabases()
// => []string{"_system", "mydb", "testdb"}
// Create a new database
err = client.CreateDatabase("analytics")
// Delete a database
err = client.DeleteDatabase("old_db")
| Method | Returns | Description |
|---|---|---|
ListDatabases() | []string, error | List all database names |
CreateDatabase(name) | error | Create new database |
DeleteDatabase(name) | error | Delete database |
Collection Operations
// List collections in a database
collections, err := client.ListCollections("mydb")
// => []string{"users", "orders", "products"}
// Create a document collection
err = client.CreateCollection("mydb", "products", nil)
// Create an edge collection (for graphs)
edgeType := "edge"
err = client.CreateCollection("mydb", "relationships", &edgeType)
// Delete a collection
err = client.DeleteCollection("mydb", "old_collection")
| Method | Returns | Description |
|---|---|---|
ListCollections(db) | []string, error | List collections in database |
CreateCollection(db, name, *type) | error | Create collection (type: nil/edge) |
DeleteCollection(db, name) | error | Delete collection |
Document Operations (CRUD)
// INSERT - Create a new document
doc, err := client.Insert("mydb", "users", map[string]interface{}{
"name": "Alice",
"email": "[email protected]",
"age": 30,
}, nil)
fmt.Println(doc["_key"]) // Auto-generated key
// INSERT with custom key
customKey := "custom-key-123"
doc, err = client.Insert("mydb", "users", map[string]interface{}{
"name": "Bob",
}, &customKey)
// GET - Retrieve a document by key
user, err := client.Get("mydb", "users", "custom-key-123")
// => map[string]interface{}{"_key": "custom-key-123", "name": "Bob", ...}
// UPDATE - Modify a document (merge = true for partial update)
err = client.Update("mydb", "users", "custom-key-123", map[string]interface{}{
"age": 25,
}, true)
// UPDATE - Replace entire document (merge = false)
err = client.Update("mydb", "users", "custom-key-123", map[string]interface{}{
"name": "Robert",
}, false)
// DELETE - Remove a document
err = client.Delete("mydb", "users", "custom-key-123")
// LIST - Paginated document listing
docs, err := client.List("mydb", "users", 50, 0) // limit: 50, offset: 0
| Method | Returns | Description |
|---|---|---|
Insert(db, col, doc, *key) | map, error | Insert document, returns doc with _key |
Get(db, col, key) | map, error | Get document by key |
Update(db, col, key, doc, merge) | error | Update document (merge or replace) |
Delete(db, col, key) | error | Delete document |
List(db, col, limit, offset) | []interface{}, error | List documents with pagination |
SDBQL Queries
// Simple query
users, err := client.Query("mydb", "FOR u IN users RETURN u", nil)
// Query with bind variables (recommended for security)
results, err := client.Query("mydb", `
FOR u IN users
FILTER u.age >= @min_age AND u.status == @status
SORT u.created_at DESC
LIMIT @limit
RETURN { name: u.name, email: u.email }
`, map[string]interface{}{
"min_age": 18,
"status": "active",
"limit": 100,
})
// Aggregation query
stats, err := client.Query("mydb", `
FOR u IN users
COLLECT status = u.status WITH COUNT INTO count
RETURN { status, count }
`, nil)
// Join query
orders, err := client.Query("mydb", `
FOR o IN orders
FOR u IN users FILTER u._key == o.user_id
RETURN { order: o, user: u.name }
`, nil)
ACID Transactions
// Begin a transaction
isolation := "read_committed"
txID, err := client.BeginTransaction("mydb", &isolation)
// Isolation levels: read_uncommitted, read_committed, repeatable_read, serializable
if err != nil {
log.Fatal(err)
}
// Perform operations within transaction
_, err = client.Insert("mydb", "accounts", map[string]interface{}{
"id": 1, "balance": 1000,
}, nil)
_, err = client.Insert("mydb", "accounts", map[string]interface{}{
"id": 2, "balance": 500,
}, nil)
if err != nil {
// Rollback on any error
client.RollbackTransaction(txID)
log.Println("Transaction rolled back:", err)
} else {
// Commit if all operations succeed
err = client.CommitTransaction(txID)
if err != nil {
log.Println("Commit failed:", err)
} else {
log.Println("Transaction committed successfully")
}
}
| Method | Returns | Description |
|---|---|---|
BeginTransaction(db, *isolation) | interface{}, error | Start transaction, returns tx_id |
CommitTransaction(txID) | error | Commit transaction |
RollbackTransaction(txID) | error | Rollback transaction |
Management Sub-Clients
Sub-clients provide namespaced access to management APIs.
Important: Call UseDatabase(name) first to set the database context.
client.Scripts()
Lua Script Endpointsclient.UseDatabase("mydb")
// Create a Lua script endpoint
script, err := client.Scripts().Create(
"hello", // name
"/api/hello", // path
[]string{"GET", "POST"}, // methods
`return { message = "Hello!" }`, // code
nil, // description (optional)
nil, // collection (optional)
)
fmt.Println("Created script:", script["_key"])
// List all scripts
scripts, err := client.Scripts().List()
for _, s := range scripts {
sm := s.(map[string]interface{})
fmt.Printf("%s -> %s\n", sm["name"], sm["path"])
}
// Get a specific script
script, err := client.Scripts().Get("script_key")
// Update script
err = client.Scripts().Update("script_key", map[string]interface{}{
"code": `return { message = "Updated!" }`,
"methods": []string{"GET"},
})
// Delete a script
err = client.Scripts().Delete("script_key")
// Get execution statistics
stats, err := client.Scripts().GetStats()
| Method | Parameters | Description |
|---|---|---|
Create | name, path, methods, code, *desc, *col | Create Lua endpoint |
List() | - | List all scripts |
Get(scriptID) | scriptID | Get script details |
Update(scriptID, updates) | scriptID, map | Update script properties |
Delete(scriptID) | scriptID | Delete script |
GetStats() | - | Execution statistics |
client.Jobs() & client.Cron()
Background Processingclient.UseDatabase("mydb")
// === JOBS ===
// List all queues
queues, _ := client.Jobs().ListQueues()
// => [{"name": "default", "pending": 5, "running": 2}, ...]
// List jobs in a queue with filters
jobs, _ := client.Jobs().ListJobs(
"default", // queue name
nil, // status filter (pending, running, completed, failed)
nil, // limit
nil, // offset
)
// Enqueue a new job
job, _ := client.Jobs().Enqueue(
"default", // queue name
"/scripts/process-order", // script path
map[string]interface{}{"order_id": 123}, // params
nil, // priority (higher = more urgent)
nil, // run_at (ISO8601 for delayed)
)
fmt.Println("Job ID:", job["_key"])
// Get job details
job, _ = client.Jobs().GetJob("job_id")
fmt.Println("Status:", job["status"])
// Cancel a pending job
client.Jobs().Cancel("job_id")
// === CRON ===
// List scheduled jobs
crons, _ := client.Cron().List()
// Create a cron job
cron, _ := client.Cron().Create(
"daily-cleanup", // name
"0 2 * * *", // schedule (every day at 2 AM)
"/scripts/cleanup", // script path
nil, // params
nil, // description
)
// Update cron schedule
client.Cron().Update("cron_id", map[string]interface{}{
"schedule": "0 3 * * *", // change to 3 AM
})
// Delete cron job
client.Cron().Delete("cron_id")
client.Triggers()
Database Triggersclient.UseDatabase("mydb")
// List all triggers
triggers, _ := client.Triggers().List()
// List triggers for a specific collection
triggers, _ = client.Triggers().ListByCollection("users")
// Create a trigger
trigger, _ := client.Triggers().Create(
"on_user_created", // name
"users", // collection
"insert", // operation: insert, update, delete
"/scripts/on-user-create", // script path
nil, // description
)
// Get trigger details
trigger, _ = client.Triggers().Get("trigger_id")
// Update trigger
client.Triggers().Update("trigger_id", map[string]interface{}{
"script_path": "/scripts/new-handler",
"enabled": false,
})
// Toggle trigger on/off
client.Triggers().Toggle("trigger_id")
// Delete trigger
client.Triggers().Delete("trigger_id")
| Event | Description |
|---|---|
insert | Fires on document creation |
update | Fires on document modification |
delete | Fires on document removal |
client.Roles() & client.Users()
Role-Based Access Control// === ROLES ===
// List all roles
roles, _ := client.Roles().List()
// Create a role with permissions
role, _ := client.Roles().Create(
"editor",
[]map[string]interface{}{
{"action": "read", "scope": "database", "database": "mydb"},
{"action": "write", "scope": "collection", "database": "mydb", "collection": "articles"},
{"action": "execute", "scope": "script", "database": "mydb"},
},
nil, // description
)
// Get role details
role, _ = client.Roles().Get("editor")
// Update role permissions
client.Roles().Update("editor", []map[string]interface{}{
{"action": "read", "scope": "database", "database": "mydb"},
{"action": "write", "scope": "database", "database": "mydb"},
}, nil)
// Delete role
client.Roles().Delete("editor")
// === USERS ===
// List all users
users, _ := client.Users().List()
// Create a user
user, _ := client.Users().Create("john", "secure_password", nil)
// Get user's assigned roles
roles, _ := client.Users().GetRoles("john")
// Assign a role to user
client.Users().AssignRole("john", "editor")
// Revoke a role from user
client.Users().RevokeRole("john", "editor")
// Get current authenticated user
me, _ := client.Users().Me()
// Get current user's permissions
permissions, _ := client.Users().MyPermissions()
// Delete user
client.Users().Delete("john")
| Action | Scopes | Description |
|---|---|---|
read | database, collection | Read documents and query |
write | database, collection | Create, update, delete documents |
admin | database, collection | Manage indexes, schema, etc. |
execute | script | Execute Lua scripts |
client.ApiKeys()
API Key Management// Create API key
key, _ := client.ApiKeys().Create(
"my-api-key", // name
[]string{"mydb"}, // databases
nil, // expiration
)
fmt.Println("API Key:", key["key"]) // Save this! Only shown once
// List all API keys
keys, _ := client.ApiKeys().List()
// Delete API key
client.ApiKeys().Delete("key_id")
Advanced Features
client.Vector()
Vector Search & AIclient.UseDatabase("mydb")
// Create a vector index
metric := "cosine" // cosine, euclidean, dot_product
idx, _ := client.Vector().CreateIndex(
"products", // collection
"product_embeddings", // index name
"embedding", // field
1536, // dimensions
&metric,
)
// Search by vector (semantic search)
embedding := getEmbedding("wireless headphones") // Your embedding function
results, _ := client.Vector().Search(
"products",
embedding,
10, // limit
nil, // filter
)
for _, r := range results {
rm := r.(map[string]interface{})
doc := rm["doc"].(map[string]interface{})
fmt.Printf("%s - Score: %v\n", doc["name"], rm["score"])
}
// Search by existing document (find similar)
similar, _ := client.Vector().SearchByDocument(
"products",
"product-123", // doc key
"embedding", // field
5, // limit
nil, // filter
)
// Quantize index (reduce memory usage)
client.Vector().Quantize("products", "product_embeddings", "binary")
// Dequantize (restore full precision)
client.Vector().Dequantize("products", "product_embeddings")
// List vector indexes
indexes, _ := client.Vector().ListIndexes("products")
// Delete index
client.Vector().DeleteIndex("products", "product_embeddings")
client.Geo()
Geospatial Queriesclient.UseDatabase("mydb")
// Create a geo index
idx, _ := client.Geo().CreateIndex("stores", "location_idx", "location")
// Find nearby locations (radius search)
nearby, _ := client.Geo().Near(
"stores",
48.8566, // latitude
2.3522, // longitude
5000, // radius in meters
20, // limit
)
for _, r := range nearby {
rm := r.(map[string]interface{})
doc := rm["doc"].(map[string]interface{})
fmt.Printf("%s - %vm away\n", doc["name"], rm["distance"])
}
// Find within polygon
polygon := [][]float64{
{48.8, 2.3}, {48.9, 2.4}, {48.85, 2.35}, {48.8, 2.3},
}
within, _ := client.Geo().Within("stores", polygon, nil)
// List geo indexes
indexes, _ := client.Geo().ListIndexes("stores")
// Delete index
client.Geo().DeleteIndex("stores", "location_idx")
client.TTL()
Time-To-Live Indexesclient.UseDatabase("mydb")
// Create TTL index (auto-expire documents after 1 hour)
idx, _ := client.TTL().CreateIndex(
"sessions",
"session_ttl",
"created_at", // DateTime field to check
3600, // expire after seconds
)
// Update expiration time
client.TTL().UpdateExpiration("sessions", "session_ttl", 7200) // 2 hours
// Get index info
info, _ := client.TTL().GetIndexInfo("sessions", "session_ttl")
fmt.Printf("Expires after: %vs\n", info["expire_after_seconds"])
// Manually trigger cleanup (normally runs automatically)
client.TTL().RunCleanup("sessions")
// List TTL indexes
indexes, _ := client.TTL().ListIndexes("sessions")
// Delete TTL index
client.TTL().DeleteIndex("sessions", "session_ttl")
client.Columnar()
Columnar/Analytics Storageclient.UseDatabase("mydb")
// Create a columnar table (optimized for analytics)
table, _ := client.Columnar().Create("metrics", []map[string]interface{}{
{"name": "timestamp", "type": "datetime"},
{"name": "metric_name", "type": "string"},
{"name": "value", "type": "float"},
{"name": "tags", "type": "string"},
})
// Insert rows (batch insert is efficient)
client.Columnar().Insert("metrics", []map[string]interface{}{
{"timestamp": "2024-01-15T10:00:00Z", "metric_name": "cpu_usage", "value": 45.2, "tags": "server1"},
{"timestamp": "2024-01-15T10:01:00Z", "metric_name": "cpu_usage", "value": 47.8, "tags": "server1"},
})
// Query with SQL-like syntax
results, _ := client.Columnar().Query("metrics",
"SELECT * FROM metrics WHERE value > @min ORDER BY timestamp DESC LIMIT 100",
map[string]interface{}{"min": 40.0},
)
// Aggregation
agg, _ := client.Columnar().Aggregate("metrics", map[string]interface{}{
"group_by": []string{"metric_name", "tags"},
"metrics": []map[string]interface{}{
{"column": "value", "function": "avg"},
{"column": "value", "function": "max"},
{"column": "value", "function": "count"},
},
})
// Get table statistics
stats, _ := client.Columnar().Stats("metrics")
fmt.Printf("Row count: %v\n", stats["row_count"])
// Add a column
client.Columnar().AddColumn("metrics", "host", "string", nil)
// Drop a column
client.Columnar().DropColumn("metrics", "host")
// List all columnar tables
tables, _ := client.Columnar().List()
// Delete table
client.Columnar().Delete("metrics")
client.Cluster()
Cluster Management// Get cluster status
status, _ := client.Cluster().Status()
fmt.Printf("Mode: %v\n", status["mode"]) // standalone, cluster
fmt.Printf("Nodes: %v\n", status["node_count"])
// Get detailed cluster info
info, _ := client.Cluster().Info()
// Remove a node from cluster
client.Cluster().RemoveNode("node-id-to-remove")
// Trigger data rebalancing
client.Cluster().Rebalance()
// Cleanup orphaned data
client.Cluster().Cleanup()
// Reshard cluster
client.Cluster().Reshard(nil) // or specify new shard count
client.Collections()
Advanced Collection Operationsclient.UseDatabase("mydb")
// Truncate collection (delete all documents)
client.Collections().Truncate("logs")
// Compact collection (reclaim disk space)
client.Collections().Compact("users")
// Repair collection (fix inconsistencies)
client.Collections().Repair("orders")
// Get collection statistics
stats, _ := client.Collections().Stats("users")
// Set JSON schema validation
client.Collections().SetSchema("users", map[string]interface{}{
"type": "object",
"required": []string{"name", "email"},
"properties": map[string]interface{}{
"name": map[string]interface{}{"type": "string", "minLength": 1},
"email": map[string]interface{}{"type": "string", "format": "email"},
},
})
// Get current schema
schema, _ := client.Collections().GetSchema("users")
// Remove schema validation
client.Collections().DeleteSchema("users")
// Export collection
data, _ := client.Collections().Export("users", nil)
// Import data
client.Collections().Import("users_backup", data, nil)
client.Env()
Environment Variablesclient.UseDatabase("mydb")
// List environment variables (for Lua scripts)
vars, _ := client.Env().List()
// Set an environment variable
client.Env().Set("API_KEY", "sk-xxx-your-api-key")
client.Env().Set("WEBHOOK_URL", "https://example.com/webhook")
// Delete an environment variable
client.Env().Delete("OLD_VAR")
Error Handling
package main
import (
"errors"
"log"
"github.com/solisoft/solidb-go-client/solidb"
)
func main() {
client := solidb.NewClient("127.0.0.1", 6745)
err := client.Connect()
if err != nil {
var connErr *solidb.ConnectionError
if errors.As(err, &connErr) {
log.Fatal("Connection failed:", connErr.Message)
}
}
defer client.Close()
err = client.Auth("mydb", "user", "password")
if err != nil {
var serverErr *solidb.ServerError
if errors.As(err, &serverErr) {
log.Println("Server error:", serverErr.Message)
}
}
doc, err := client.Get("mydb", "users", "nonexistent-key")
if err != nil {
var serverErr *solidb.ServerError
var protoErr *solidb.ProtocolError
switch {
case errors.As(err, &serverErr):
log.Println("Document not found or other server error:", serverErr.Message)
case errors.As(err, &protoErr):
log.Println("Protocol error:", protoErr.Message)
default:
log.Println("Unknown error:", err)
}
}
}
ConnectionError
Network failures, connection refused, timeouts, disconnections
ServerError
Document not found, permission denied, validation errors
ProtocolError
Invalid response format, message too large, serialization issues