Go
|
Connection options for Go ArcadeDB exposes multiple wire protocols, so you can pick the one your stack already speaks:
This tutorial uses the PostgreSQL wire protocol, which is the right choice when you already run a PostgreSQL stack. |
This tutorial shows how to connect to ArcadeDB from Go using the PostgreSQL wire protocol and pgx. You will create a graph, query it with SQL and Cypher, and run a vector search.
Prerequisites
-
ArcadeDB running with the PostgreSQL protocol enabled (default port 5432)
-
Go 1.25+ (required by pgx v5)
-
The
pgxdriver
go get github.com/jackc/pgx/v5
Connect to ArcadeDB
No ArcadeDB-specific SDK is needed. pgx connects with an ordinary PostgreSQL connection string:
package main
import (
"context"
"fmt"
"log"
"github.com/jackc/pgx/v5"
)
func main() {
ctx := context.Background()
conn, err := pgx.Connect(ctx,
"postgres://root:arcadedb@localhost:5432/mydb?sslmode=disable&default_query_exec_mode=exec")
if err != nil {
log.Fatal(err)
}
defer conn.Close(ctx)
fmt.Println("Connected to ArcadeDB")
}
|
Why By default, pgx prepares each statement and asks the server for its parameter types. ArcadeDB reports
every parameter as text, so pgx then refuses to send a Go
In |
Create a Schema
Use SQL to create vertex and edge types, then insert some data:
for _, stmt := range []string{
"CREATE VERTEX TYPE Person IF NOT EXISTS",
"CREATE VERTEX TYPE Movie IF NOT EXISTS",
"CREATE EDGE TYPE Acted IF NOT EXISTS",
"CREATE VERTEX Person SET name = 'Alice', age = 30",
"CREATE VERTEX Person SET name = 'Bob', age = 25",
"CREATE VERTEX Movie SET title = 'The Matrix', year = 1999",
`CREATE EDGE Acted FROM (SELECT FROM Person WHERE name = 'Alice')
TO (SELECT FROM Movie WHERE title = 'The Matrix')
SET role = 'Trinity'`,
} {
if _, err := conn.Exec(ctx, stmt); err != nil {
log.Fatalf("%s: %v", stmt, err)
}
}
Parameters use PostgreSQL’s $1, $2 placeholders:
tag, err := conn.Exec(ctx, "CREATE VERTEX Person SET name = $1, age = $2", "Carol", 41)
if err != nil {
log.Fatal(err)
}
fmt.Println(tag)
INSERT 0 1
Query with SQL
rows, err := conn.Query(ctx, `
MATCH {type: Person, as: person}.outE('Acted'){as: acted}.inV(){type: Movie, as: movie}
RETURN person.name AS name, movie.title AS title, acted.role AS role`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name, title, role string
if err := rows.Scan(&name, &title, &role); err != nil {
log.Fatal(err)
}
fmt.Printf("%s acted in %s as %s\n", name, title, role)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
Alice acted in The Matrix as Trinity
Always check rows.Err() after the loop: rows.Next() returns false both at the end of the
result and on an error, and only rows.Err() tells the two apart.
Query with Cypher
ArcadeDB supports Cypher queries through the same connection:
rows, err := conn.Query(ctx,
"{cypher} MATCH (p:Person)-[a:Acted]->(m:Movie) RETURN p.name AS name, m.title AS title, a.role AS role")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name, title, role string
if err := rows.Scan(&name, &title, &role); err != nil {
log.Fatal(err)
}
fmt.Printf("%s acted in %s as %s\n", name, title, role)
}
Prefix Cypher queries with {cypher} when using the PostgreSQL protocol.
|
Vector Search
Add embeddings to your data and query by similarity:
for _, stmt := range []string{
// A type with a vector property and an index on it
"CREATE VERTEX TYPE Product IF NOT EXISTS",
"CREATE PROPERTY Product.embedding IF NOT EXISTS LIST OF FLOAT",
"CREATE INDEX IF NOT EXISTS ON Product (embedding) LSM_VECTOR METADATA {dimensions: 4, similarity: 'COSINE'}",
// Products with embeddings
"CREATE VERTEX Product SET name = 'Laptop', embedding = [0.9, 0.1, 0.8, 0.2]",
"CREATE VERTEX Product SET name = 'Tablet', embedding = [0.8, 0.2, 0.7, 0.3]",
"CREATE VERTEX Product SET name = 'Phone', embedding = [0.7, 0.3, 0.6, 0.4]",
"CREATE VERTEX Product SET name = 'Book', embedding = [0.1, 0.9, 0.2, 0.8]",
} {
if _, err := conn.Exec(ctx, stmt); err != nil {
log.Fatalf("%s: %v", stmt, err)
}
}
// Find the 3 products most similar to a query vector
rows, err := conn.Query(ctx, `
SELECT name, distance FROM (
SELECT expand(vector.neighbors('Product[embedding]', [0.85, 0.15, 0.75, 0.25], 3))
)`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
fmt.Println("Similar products:")
for rows.Next() {
var name string
var distance float64
if err := rows.Scan(&name, &distance); err != nil {
log.Fatal(err)
}
fmt.Printf(" %s (%.4f)\n", name, distance)
}
Similar products:
Laptop (0.0025)
Tablet (0.0029)
Phone (0.0306)
See the vector search tutorial for the index options and similarity functions.
Full Example
// ArcadeDB Go quickstart: a small graph queried over the PostgreSQL protocol.
package main
import (
"context"
"fmt"
"log"
"github.com/jackc/pgx/v5"
)
func main() {
ctx := context.Background()
conn, err := pgx.Connect(ctx,
"postgres://root:arcadedb@localhost:5432/mydb?sslmode=disable&default_query_exec_mode=exec")
if err != nil {
log.Fatal(err)
}
defer conn.Close(ctx)
// Create schema and data
for _, stmt := range []string{
"CREATE VERTEX TYPE Person IF NOT EXISTS",
"CREATE VERTEX TYPE Movie IF NOT EXISTS",
"CREATE EDGE TYPE Acted IF NOT EXISTS",
"CREATE VERTEX Person SET name = 'Alice', age = 30",
"CREATE VERTEX Movie SET title = 'The Matrix', year = 1999",
`CREATE EDGE Acted FROM (SELECT FROM Person WHERE name = 'Alice')
TO (SELECT FROM Movie WHERE title = 'The Matrix')
SET role = 'Trinity'`,
} {
if _, err := conn.Exec(ctx, stmt); err != nil {
log.Fatalf("%s: %v", stmt, err)
}
}
// Query with SQL MATCH
rows, err := conn.Query(ctx, `
MATCH {type: Person, as: person}.outE('Acted'){as: acted}.inV(){type: Movie, as: movie}
RETURN person.name AS name, movie.title AS title, acted.role AS role`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name, title, role string
if err := rows.Scan(&name, &title, &role); err != nil {
log.Fatal(err)
}
fmt.Printf("%s acted in %s as %s\n", name, title, role)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}
Next Steps
-
Go HTTP driver — the native driver, which adds ArcadeDB’s batch loading and vector search APIs