Astra DB Serverless quickstart for tables (Go)
|
If your data is not fully structured, or if you do not want to use a fixed schema, see the quickstart for collections instead. This quickstart requires a Serverless (vector) database. For Serverless (non-vector) databases, see Get started with the Data API (Go). |
This quickstart demonstrates how to create a table schema, insert data to a table, generate vector embeddings, and perform a vector search to find similar data.
The Next steps section discusses how to insert other types of data, use a different embedding model, insert data with pre-generated vector embeddings, or skip embedding generation.
To learn more about vector databases and vector search, see What are vector databases? and What is Vector Search.
Create a database and store your credentials
-
Click Create database.
-
For this quickstart, select the following:
-
Type: Serverless (vector)
-
Provider: Amazon Web Services
-
Region: us-east-2
-
-
If applicable to your organization, you can select or create a PCU group for the database.
-
Click Create database.
Wait for your database to initialize and reach Active status. This can take several minutes.
-
Under Database Details, copy your database’s API endpoint.
-
Under Database Details, click Generate Token, then copy the token.
-
For this quickstart, store the endpoint and token in environment variables:
-
Linux or macOS
-
Windows
export API_ENDPOINT=API_ENDPOINT export APPLICATION_TOKEN=APPLICATION_TOKENset API_ENDPOINT=API_ENDPOINTset APPLICATION_TOKEN=APPLICATION_TOKEN -
Install a client
Install one of the Data API clients to facilitate interactions with the Data API. To use the Data API with tables, you must install client version 2.0.x.
-
Update to Go version 1.23 or later if needed.
-
Install the latest version of the astra-db-go package.
For example:
go get github.com/datastax/astra-db-go/v2
To test pre-generated commands without installing a client, you can use the Data API console in the Astra Portal. The scripts used in this quickstart aren’t compatible with the Data API console because they are intended for use with a Data API client.
Connect to your database
The following function will connect to your database.
Copy the file into your project. You don’t need to execute the function now; the subsequent code examples will import and use this function.
package shared
import (
"fmt"
"log"
"os"
"github.com/datastax/astra-db-go/v2/astra"
"github.com/datastax/astra-db-go/v2/astra/options"
)
// ConnectToDatabase connects to a DataStax Astra database.
// This function retrieves the database endpoint and application token
// from the environment variables `API_ENDPOINT` and `APPLICATION_TOKEN`.
//
// Returns an instance of the connected database.
// Exits with an error if the environment variables
// `API_ENDPOINT` or `APPLICATION_TOKEN` are not defined.
func ConnectToDatabase() *astra.Db {
endpoint := os.Getenv("API_ENDPOINT") (1)
token := os.Getenv("APPLICATION_TOKEN")
if token == "" || endpoint == "" {
log.Fatal(
"Environment variables API_ENDPOINT and APPLICATION_TOKEN must be defined.",
)
}
// Create an instance of `DataAPIClient`
client := astra.NewClient()
// Get the database specified by your endpoint and provide the token
database := client.Database(endpoint, options.API().SetToken(token))
fmt.Printf("Connected to database %s\n", database.Endpoint())
return database
}
| 1 | Store your database’s endpoint and application token in environment variables named API_ENDPOINT and APPLICATION_TOKEN, as instructed in Create a database and store your credentials. |
Create a table
The following code will create an empty table in your database. The table created here matches the structure of the data that you will insert to the table. After creating the table, the code will index some columns so that you can find and sort data in those columns.
-
Copy the code into your project.
-
If needed, update the import path to the "connect to database" function from the previous section.
-
Execute the code.
For information about executing code, refer to the documentation for your programming language.
Once the code completes, you should see a printed message confirming the table creation.
package main
import (
"context"
"fmt"
"log"
"quickstart/shared"
"github.com/datastax/astra-db-go/v2/astra/options"
"github.com/datastax/astra-db-go/v2/astra/table"
)
func main() {
ctx := context.Background()
database := shared.ConnectToDatabase() (1)
// Define all of the columns in the table
definition := table.Definition{
Columns: table.Columns{
{Name: "title", Column: table.Text()},
{Name: "author", Column: table.Text()},
{Name: "number_of_pages", Column: table.Int()},
{Name: "rating", Column: table.Float()},
{Name: "publication_year", Column: table.Int()},
{Name: "summary", Column: table.Text()},
{Name: "genres", Column: table.Set(table.Text())},
{Name: "metadata", Column: table.Map("text", table.Text())},
{Name: "is_checked_out", Column: table.Boolean()},
{Name: "borrower", Column: table.Text()},
{Name: "due_date", Column: table.Date()},
// This column will store vector embeddings.
// The column will use an embedding model from NVIDIA to
// generate the
// vector embeddings when data is inserted to the column. (2)
{
Name: "summary_genres_vector",
Column: table.VectorWithService(
1024,
&table.VectorService{
Provider: "nvidia",
ModelName: "nvidia/nv-embedqa-e5-v5",
},
),
},
},
// Define the primary key for the table.
// In this case, the table uses a composite primary key.
PrimaryKey: table.PrimaryKey{
PartitionBy: []string{"title", "author"},
},
}
table, err := database.CreateTable(
ctx,
"quickstart_table", (3)
definition,
)
if err != nil {
log.Fatal(err)
}
fmt.Println("Created table")
// Index any columns that you want to sort and filter on.
err = table.CreateIndex(ctx, "rating_index", "rating")
if err != nil {
log.Fatal(err)
}
err = table.CreateIndex(
ctx,
"number_of_pages_index",
"number_of_pages",
)
if err != nil {
log.Fatal(err)
}
err = table.CreateVectorIndex(
ctx,
"summary_genres_vector_index",
"summary_genres_vector",
options.CreateVectorIndex().SetMetric(options.MetricCosine),
)
if err != nil {
log.Fatal(err)
}
fmt.Println("Indexed columns")
}
| 1 | This is the connectToDatabase function from the previous section. Update the import path if necessary.
To use the function, ensure you stored your database’s endpoint and application token in environment variables as instructed in Create a database and store your credentials. |
| 2 | This column will use the Astra-hosted NVIDIA embedding model to generate vector embeddings. This is currently only supported in certain regions. Ensure that your database is in the Amazon Web Services us-east-2 region, as instructed in Create a database and store your credentials. |
| 3 | This code creates a table named quickstart_table. If you want to use a different name, change the name before running the code. |
Insert data to your table
The following code will insert data from a JSON file into a your table.
-
Copy the code into your project.
-
Download the quickstart_dataset.json sample dataset (76 kB). This dataset is a JSON array describing library books.
-
Replace
PATH_TO_DATA_FILEin the code with the path to the dataset. -
If needed, update the import path to the "connect to database" function from the previous section.
-
Execute the code.
For information about executing code, refer to the documentation for your programming language.
Once the code completes, you should see a printed message confirming the insertion of 100 rows.
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"strings"
"quickstart/shared"
"github.com/datastax/astra-db-go/v2/astra"
"github.com/datastax/astra-db-go/v2/astra/datatypes"
)
func main() {
ctx := context.Background()
database := shared.ConnectToDatabase() (1)
table := database.Table("quickstart_table") (2)
dataFilePath := "PATH_TO_DATA_FILE" (3)
// Read the JSON file and parse it into a JSON array
rawData, err := os.ReadFile(dataFilePath)
if err != nil {
log.Fatal(err)
}
var jsonData []map[string]any
if err := json.Unmarshal(rawData, &jsonData); err != nil {
log.Fatal(err)
}
rows := make([]astra.Row, len(jsonData))
for i, data := range jsonData {
// Convert due_date string to DateOnly type if present
if dueDateStr, ok := data["due_date"].(string); ok &&
dueDateStr != "" {
dueDate, err := datatypes.ParseDateOnly(dueDateStr)
if err != nil {
log.Fatalf("invalid due_date %q: %v", dueDateStr, err)
}
data["due_date"] = dueDate
}
// Create the summary_genres_vector text to vectorize
summary, _ := data["summary"].(string)
genres := []string{}
if g, ok := data["genres"].([]any); ok {
for _, genre := range g {
if genreStr, ok := genre.(string); ok {
genres = append(genres, genreStr)
}
}
}
data["summary_genres_vector"] = fmt.Sprintf(
"summary: %s | genres: %s",
summary,
strings.Join(genres, ", "),
)
rows[i] = astra.NewRow(data)
}
insertedResult, err := table.InsertMany(ctx, rows)
if err != nil {
log.Fatal(err)
}
fmt.Printf(
"Inserted %d rows.\n",
insertedResult.InsertedCount(),
)
}
| 1 | This is the connectToDatabase function from the previous section. Update the import path if necessary.
To use the function, ensure you stored your database’s endpoint and application token in environment variables as instructed in Create a database and store your credentials. |
| 2 | If you changed the table name in the previous code, change it in this code as well. |
| 3 | Replace PATH_TO_DATA_FILE with the path to the JSON data file. |
Find data in your table
After you insert data to your table, you can search the data. In addition to traditional database filtering, you can perform a vector search to find data that is most similar to a search string.
The following code performs three searches on the sample data that you loaded in Insert data to your table.
package main
import (
"context"
"fmt"
"log"
"quickstart/shared"
"github.com/datastax/astra-db-go/v2/astra"
"github.com/datastax/astra-db-go/v2/astra/filter"
"github.com/datastax/astra-db-go/v2/astra/options"
"github.com/datastax/astra-db-go/v2/astra/sort"
)
func main() {
ctx := context.Background()
database := shared.ConnectToDatabase() (1)
table := database.Table("quickstart_table") (2)
// Find rows that match a filter
fmt.Println("\nFinding books with rating greater than 4.7...")
ratingCursor := table.Find(
filter.Gt("rating", 4.7),
options.TableFind().
SetLimit(10).
SetProjection(map[string]any{"title": true, "rating": true}),
)
defer ratingCursor.Close()
for ratingCursor.Next(ctx) {
var row astra.Row
if err := ratingCursor.Decode(&row); err != nil {
log.Fatal(err)
}
fmt.Printf(
"%s is rated %.1f\n",
row.MustGet("title"),
row.MustGet(("rating")),
)
}
if err := ratingCursor.Err(); err != nil {
log.Fatal(err)
}
// Perform a vector search to find the closest match to a search string
fmt.Println("\nUsing vector search to find a single scary novel...")
var singleVectorMatch astra.Row
err := table.FindOne(
ctx,
nil,
options.TableFindOne().
SetSort(sort.Table.Vectorize("summary_genres_vector", "A scary novel")).
SetProjection(map[string]any{"title": true}),
).Decode(&singleVectorMatch)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s is a scary novel\n", singleVectorMatch.MustGet("title"))
// Combine a filter, vector search, and projection to find the 3 books
// with
// more than 400 pages that are the closest matches to a search string
// and just return the title and author
fmt.Println(
"\nUsing filters and vector search to find 3 books with more than 400 pages that are set in the arctic, returning just the title and author...",
)
vectorCursor := table.Find(
filter.Gt("number_of_pages", 400),
options.TableFind().
SetSort(sort.Table.Vectorize("summary_genres_vector", "A book set in the arctic")).
SetLimit(3).
SetProjection(map[string]any{"title": true, "author": true}),
)
defer vectorCursor.Close()
for vectorCursor.Next(ctx) {
var row astra.Row
if err := vectorCursor.Decode(&row); err != nil {
log.Fatal(err)
}
fmt.Printf(
"Title: %s, Author: %s\n",
row.MustGet("title"),
row.MustGet("author"),
)
}
if err := vectorCursor.Err(); err != nil {
log.Fatal(err)
}
}
| 1 | This is the connectToDatabase function from the previous section. Update the import path if necessary. |
| 2 | If you changed the table name in the previous code, change it in this code as well. |
Next steps
For more practice, you can continue building with the table that you created here. For example, try inserting more data to the table, or try different searches. The Data API reference provides code examples for various operations.
- Insert data from different sources
-
This quickstart demonstrated how to insert structured data from a JSON file into a table, but you can insert data from many sources.
Tables use fixed schemas. If your data is unstructured or if you want a flexible schema, you can use a collection instead of a table. See the quickstart for collections.
- Use a different method to generate vector embeddings
-
This quickstart used the Astra-hosted NVIDIA embedding model to generate vector embeddings. You can also use other embedding models, or you can insert data with pre-generated vector embeddings (or without vector embeddings) and skip embedding.
-
To use a different embedding model, see Generate and store embeddings in Astra DB Serverless databases and Work with rows: Vector type.
-
To insert pre-embedded data, you need to specify the vector dimensions and similarity metric instead of specifying the embedding provider. See Work with rows: Vector type.
-
- Perform more complex searches
-
This quickstart demonstrated how to find data using filters and vector search. To learn more about the searches you can perform, see Ways to find data in Astra DB Serverless.
- Use different database settings
-
For this quickstart, you need a Serverless (vector) database in the Amazon Web Services us-east-2 region, which is required for the Astra-hosted NVIDIA embedding model integration. For production databases, you might use different database settings. For more information, see Astra DB Serverless database regions and maintenance schedules and Create an Astra DB Serverless database.