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