Chương này giới thiệu cách nhanh chóng bắt đầu với các hoạt động đọc và ghi của cơ sở dữ liệu vector Milvus bằng Go.

Cài đặt Go SDK

Lưu ý: Go SDK yêu cầu phiên bản Go 1.15 trở lên.

go get -u github.com/milvus-io/milvus-sdk-go/v2

Nhập các phụ thuộc

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"
)

Kết nối đến cơ sở dữ liệu Milvus

	ctx := context.Background()

	log.Printf(msgFmt, "Đang kết nối đến Milvus")
	c, err := client.NewClient(ctx, client.Config{
		Address: "localhost:19530",
	})
	if err != nil {
		log.Fatal("Kết nối đến Milvus thất bại, lỗi: ", err.Error())
	}
	defer c.Close()

Tạo bộ sưu tập (Collection)

Quá trình tạo bộ sưu tập tương tự như việc tạo cấu trúc bảng MySQL, trong đó bạn cần mô tả loại của mỗi trường.

   collectionName = "hello_tizi365"
	log.Printf(msgFmt, fmt.Sprintf("Đang tạo bộ sưu tập, `%s`", collectionName))
	
	// Định nghĩa loại trường của bộ sưu tập, ở đây định nghĩa các trường ID, random, và embeddings
	schema := entity.NewSchema().WithName(collectionName).WithDescription("Mô tả bộ sưu tập").
		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))

	// Tạo bộ sưu tập dựa trên loại trường bộ sưu tập được định nghĩa
	if err := c.CreateCollection(ctx, schema, entity.DefaultShardNumber); err != nil {
		log.Fatalf("Tạo bộ sưu tập thất bại, lỗi: %v", err)
	}

Chèn dữ liệu vào bộ sưu tập

	idList, randomList := make([]int64, 0, nEntities), make([]float64, 0, nEntities)
	embeddingList := make([][]float32, 0, nEntities)

	rand.Seed(time.Now().UnixNano())

    // Ví dụ cho mục đích kiểm thử, tạo dữ liệu kiểm thử ngẫu nhiên ở đây
	// Tạo IDs
	for i := 0; i < nEntities; i++ {
		idList = append(idList, int64(i))
	}
	// Tạo giá trị ngẫu nhiên
	for i := 0; i < nEntities; i++ {
		randomList = append(randomList, rand.Float64())
	}
	// Tạo giá trị vector
	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)
	}
	// Chèn nhiều bộ dữ liệu, tổ chức theo cột cho nhiều dữ liệu
	idColData := entity.NewColumnInt64("ID", idList)
	randomColData := entity.NewColumnDouble("random", randomList)
	embeddingColData := entity.NewColumnFloatVector("embeddings", dim, embeddingList)

    // Chèn dữ liệu
	if _, err := c.Insert(ctx, collectionName, "", idColData, randomColData, embeddingColData); err != nil {
		log.Fatalf("Ghi dữ liệu thất bại, lỗi: %v", err)
	}
    
	// Xả dữ liệu xuống đĩa
	if err := c.Flush(ctx, collectionName, false); err != nil {
		log.Fatalf("Xả dữ liệu thất bại, lỗi: %v", err)
	}

Tạo chỉ mục (Index)

	// Định nghĩa loại chỉ mục
	idx, err := entity.NewIndexIvfFlat(entity.L2, 128)
	if err != nil {
		log.Fatalf("Định nghĩa chỉ mục thất bại, lỗi: %v", err)
	}
	// Tạo chỉ mục cho bộ sưu tập đã chỉ định
	if err := c.CreateIndex(ctx, collectionName, embeddingCol, idx, false); err != nil {
		log.Fatalf("Tạo chỉ mục thất bại, lỗi: %v", err)
	}

    // Tải bộ sưu tập đã chỉ định vào bộ nhớ để cải thiện hiệu suất truy vấn
	err = c.LoadCollection(ctx, collectionName, false)
	if err != nil {
		log.Fatalf("Tải bộ sưu tập thất bại, lỗi: %v", err)
	}

Tìm kiếm tương đồng vector

   // Chuẩn bị các vector cần tìm kiếm. Ở đây chúng tôi trích xuất một phần dữ liệu vector từ dữ liệu đã tạo trước đó để kiểm tra, và chúng tôi sẽ tìm kiếm kết quả tương tự với các vector dưới đây.
	vec2search := []entity.Vector{
		entity.FloatVector(embeddingList[len(embeddingList)-2]),
		entity.FloatVector(embeddingList[len(embeddingList)-1]),
	}
	begin := time.Now()
	sp, _ := entity.NewIndexIvfFlatSearchParam(16)
	// Thực hiện tìm kiếm tương đồng vector
	sRet, err := c.Search(ctx, collectionName, nil, "", []string{"random"}, vec2search,
		"embeddings", entity.L2, topK, sp)
	end := time.Now()
	if err != nil {
		log.Fatalf("Tìm kiếm thất bại, lỗi: %v", err)
	}

	log.Println("In kết quả:")
	for _, res := range sRet {
		printResult(&res)
	}

Định nghĩa hàm printResult

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)
}

Toàn bộ mã nguồn minh họa, Mã nguồn Bắt đầu sử dụng Go Milvus