This chapter introduces how to quickly get started with the read and write operations of Milvus vector database using Go.
Installing the Go SDK
Note: The Go SDK requires Go version 1.15 or higher.
go get -u github.com/milvus-io/milvus-sdk-go/v2
Importing Dependencies
import (
"context"
"fmt"
"log"
"math/rand"
"time"
"github.com/milvus-io/milvus-sdk-go/v2/client"
"github.com/milvus-io/milvus-sdk-go/v2/entity"
)
Connecting to the Milvus Database
ctx := context.Background()
log.Printf(msgFmt, "Connecting to Milvus")
c, err := client.NewClient(ctx, client.Config{
Address: "localhost:19530",
})
if err != nil {
log.Fatal("Failed to connect to Milvus, err: ", err.Error())
}
defer c.Close()
Creating a Collection
The process of creating a collection is similar to creating a MySQL table structure, where you need to describe the type of each field.
collectionName = "hello_tizi365"
log.Printf(msgFmt, fmt.Sprintf("Creating collection, `%s`", collectionName))
// Define the field types of the collection, defining ID, random, and embeddings fields here
schema := entity.NewSchema().WithName(collectionName).WithDescription("Collection description").
WithField(entity.NewField().WithName("ID").WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true).WithIsAutoID(false)).
WithField(entity.NewField().WithName("random").WithDataType(entity.FieldTypeDouble)).
WithField(entity.NewField().WithName("embeddings").WithDataType(entity.FieldTypeFloatVector).WithDim(dim))
// Create the collection based on the defined collection field types
if err := c.CreateCollection(ctx, schema, entity.DefaultShardNumber); err != nil {
log.Fatalf("Failed to create collection, err: %v", err)
}
Inserting Data into the Collection
idList, randomList := make([]int64, 0, nEntities), make([]float64, 0, nEntities)
embeddingList := make([][]float32, 0, nEntities)
rand.Seed(time.Now().UnixNano())
// For testing purposes, generate some random test data here
// Generate IDs
for i := 0; i < nEntities; i++ {
idList = append(idList, int64(i))
}
// Generate random values
for i := 0; i < nEntities; i++ {
randomList = append(randomList, rand.Float64())
}
// Generate vector values
for i := 0; i < nEntities; i++ {
vec := make([]float32, 0, dim)
for j := 0; j < dim; j++ {
vec = append(vec, rand.Float32())
}
embeddingList = append(embeddingList, vec)
}
// Insert multiple data sets, organized by column for multiple data
idColData := entity.NewColumnInt64("ID", idList)
randomColData := entity.NewColumnDouble("random", randomList)
embeddingColData := entity.NewColumnFloatVector("embeddings", dim, embeddingList)
// Insert data
if _, err := c.Insert(ctx, collectionName, "", idColData, randomColData, embeddingColData); err != nil {
log.Fatalf("Failed to write data, err: %v", err)
}
// Flush data to disk
if err := c.Flush(ctx, collectionName, false); err != nil {
log.Fatalf("Failed to flush data, err: %v", err)
}
Creating Index
// Define index type
idx, err := entity.NewIndexIvfFlat(entity.L2, 128)
if err != nil {
log.Fatalf("Failed to define index, err: %v", err)
}
// Create index for the specified collection
if err := c.CreateIndex(ctx, collectionName, embeddingCol, idx, false); err != nil {
log.Fatalf("Failed to create index, err: %v", err)
}
// Load the specified collection into memory to improve query efficiency
err = c.LoadCollection(ctx, collectionName, false)
if err != nil {
log.Fatalf("Failed to load collection, err: %v", err)
}
Vector Similarity Search
// Prepare the vectors to be searched. Here we extract part of the vector data from the previously generated data for testing, and we will search for results similar to these vectors below.
vec2search := []entity.Vector{
entity.FloatVector(embeddingList[len(embeddingList)-2]),
entity.FloatVector(embeddingList[len(embeddingList)-1]),
}
begin := time.Now()
sp, _ := entity.NewIndexIvfFlatSearchParam(16)
// Perform vector similarity search
sRet, err := c.Search(ctx, collectionName, nil, "", []string{"random"}, vec2search,
"embeddings", entity.L2, topK, sp)
end := time.Now()
if err != nil {
log.Fatalf("Search failed, err: %v", err)
}
log.Println("Print results:")
for _, res := range sRet {
printResult(&res)
}
printResult function definition
func printResult(sRet *client.SearchResult) {
randoms := make([]float64, 0, sRet.ResultCount)
scores := make([]float32, 0, sRet.ResultCount)
var randCol *entity.ColumnDouble
for _, field := range sRet.Fields {
if field.Name() == randomCol {
c, ok := field.(*entity.ColumnDouble)
if ok {
randCol = c
}
}
}
for i := 0; i < sRet.ResultCount; i++ {
val, err := randCol.ValueByIdx(i)
if err != nil {
log.Fatal(err)
}
randoms = append(randoms, val)
scores = append(scores, sRet.Scores[i])
}
log.Printf("\trandoms: %v, scores: %v\n", randoms, scores)
}
Complete demonstration source code, Go Milvus Getting Started Source Code