github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/examples/hello_milvus/hello_milvus.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"math/rand"
     8  	"time"
     9  
    10  	"github.com/milvus-io/milvus-sdk-go/v2/client"
    11  	"github.com/milvus-io/milvus-sdk-go/v2/entity"
    12  )
    13  
    14  const (
    15  	milvusAddr     = `localhost:19530`
    16  	nEntities, dim = 3000, 128
    17  	collectionName = "hello_milvus"
    18  
    19  	msgFmt                         = "==== %s ====\n"
    20  	idCol, randomCol, embeddingCol = "ID", "random", "embeddings"
    21  	topK                           = 3
    22  )
    23  
    24  func main() {
    25  	ctx := context.Background()
    26  
    27  	log.Printf(msgFmt, "start connecting to Milvus")
    28  	c, err := client.NewClient(ctx, client.Config{
    29  		Address: milvusAddr,
    30  	})
    31  	if err != nil {
    32  		log.Fatal("failed to connect to milvus, err: ", err.Error())
    33  	}
    34  	defer c.Close()
    35  
    36  	// delete collection if exists
    37  	has, err := c.HasCollection(ctx, collectionName)
    38  	if err != nil {
    39  		log.Fatalf("failed to check collection exists, err: %v", err)
    40  	}
    41  	if has {
    42  		c.DropCollection(ctx, collectionName)
    43  	}
    44  
    45  	// create collection
    46  	log.Printf(msgFmt, fmt.Sprintf("create collection, `%s`", collectionName))
    47  	schema := entity.NewSchema().WithName(collectionName).WithDescription("hello_milvus is the simplest demo to introduce the APIs").
    48  		WithField(entity.NewField().WithName(idCol).WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true).WithIsAutoID(false)).
    49  		WithField(entity.NewField().WithName(randomCol).WithDataType(entity.FieldTypeDouble)).
    50  		WithField(entity.NewField().WithName(embeddingCol).WithDataType(entity.FieldTypeFloatVector).WithDim(dim))
    51  
    52  	if err := c.CreateCollection(ctx, schema, entity.DefaultShardNumber); err != nil { // use default shard number
    53  		log.Fatalf("create collection failed, err: %v", err)
    54  	}
    55  
    56  	// insert data
    57  	log.Printf(msgFmt, "start inserting random entities")
    58  	idList, randomList := make([]int64, 0, nEntities), make([]float64, 0, nEntities)
    59  	embeddingList := make([][]float32, 0, nEntities)
    60  
    61  	rand.Seed(time.Now().UnixNano())
    62  
    63  	// generate data
    64  	for i := 0; i < nEntities; i++ {
    65  		idList = append(idList, int64(i))
    66  	}
    67  	for i := 0; i < nEntities; i++ {
    68  		randomList = append(randomList, rand.Float64())
    69  	}
    70  	for i := 0; i < nEntities; i++ {
    71  		vec := make([]float32, 0, dim)
    72  		for j := 0; j < dim; j++ {
    73  			vec = append(vec, rand.Float32())
    74  		}
    75  		embeddingList = append(embeddingList, vec)
    76  	}
    77  	idColData := entity.NewColumnInt64(idCol, idList)
    78  	randomColData := entity.NewColumnDouble(randomCol, randomList)
    79  	embeddingColData := entity.NewColumnFloatVector(embeddingCol, dim, embeddingList)
    80  
    81  	if _, err := c.Insert(ctx, collectionName, "", idColData, randomColData, embeddingColData); err != nil {
    82  		log.Fatalf("failed to insert random data into `hello_milvus, err: %v", err)
    83  	}
    84  
    85  	if err := c.Flush(ctx, collectionName, false); err != nil {
    86  		log.Fatalf("failed to flush data, err: %v", err)
    87  	}
    88  
    89  	// build index
    90  	log.Printf(msgFmt, "start creating index IVF_FLAT")
    91  	idx, err := entity.NewIndexIvfFlat(entity.L2, 128)
    92  	if err != nil {
    93  		log.Fatalf("failed to create ivf flat index, err: %v", err)
    94  	}
    95  	if err := c.CreateIndex(ctx, collectionName, embeddingCol, idx, false); err != nil {
    96  		log.Fatalf("failed to create index, err: %v", err)
    97  	}
    98  
    99  	log.Printf(msgFmt, "start loading collection")
   100  	err = c.LoadCollection(ctx, collectionName, false)
   101  	if err != nil {
   102  		log.Fatalf("failed to load collection, err: %v", err)
   103  	}
   104  
   105  	log.Printf(msgFmt, "start searcching based on vector similarity")
   106  	vec2search := []entity.Vector{
   107  		entity.FloatVector(embeddingList[len(embeddingList)-2]),
   108  		entity.FloatVector(embeddingList[len(embeddingList)-1]),
   109  	}
   110  	begin := time.Now()
   111  	sp, _ := entity.NewIndexIvfFlatSearchParam(16)
   112  	sRet, err := c.Search(ctx, collectionName, nil, "", []string{randomCol}, vec2search,
   113  		embeddingCol, entity.L2, topK, sp)
   114  	end := time.Now()
   115  	if err != nil {
   116  		log.Fatalf("failed to search collection, err: %v", err)
   117  	}
   118  
   119  	log.Println("results:")
   120  	for _, res := range sRet {
   121  		printResult(&res)
   122  	}
   123  	log.Printf("\tsearch latency: %dms\n", end.Sub(begin)/time.Millisecond)
   124  
   125  	// hybrid search
   126  	log.Printf(msgFmt, "start hybrid searching with `random > 0.5`")
   127  	begin = time.Now()
   128  	sRet2, err := c.Search(ctx, collectionName, nil, "random > 0.5",
   129  		[]string{randomCol}, vec2search, embeddingCol, entity.L2, topK, sp)
   130  	end = time.Now()
   131  	if err != nil {
   132  		log.Fatalf("failed to search collection, err: %v", err)
   133  	}
   134  	log.Println("results:")
   135  	for _, res := range sRet2 {
   136  		printResult(&res)
   137  	}
   138  	log.Printf("\tsearch latency: %dms\n", end.Sub(begin)/time.Millisecond)
   139  
   140  	// delete data
   141  	log.Printf(msgFmt, "start deleting with expr ``")
   142  	pks := entity.NewColumnInt64(idCol, []int64{0, 1})
   143  	sRet3, err := c.QueryByPks(ctx, collectionName, nil, pks, []string{randomCol})
   144  	if err != nil {
   145  		log.Fatalf("failed to query result, err: %v", err)
   146  	}
   147  	log.Println("results:")
   148  	idlist := make([]int64, 0)
   149  	randList := make([]float64, 0)
   150  
   151  	for _, col := range sRet3 {
   152  		if col.Name() == idCol {
   153  			idColumn := col.(*entity.ColumnInt64)
   154  			for i := 0; i < col.Len(); i++ {
   155  				val, err := idColumn.ValueByIdx(i)
   156  				if err != nil {
   157  					log.Fatal(err)
   158  				}
   159  				idlist = append(idlist, val)
   160  			}
   161  		} else {
   162  			randColumn := col.(*entity.ColumnDouble)
   163  			for i := 0; i < col.Len(); i++ {
   164  				val, err := randColumn.ValueByIdx(i)
   165  				if err != nil {
   166  					log.Fatal(err)
   167  				}
   168  				randList = append(randList, val)
   169  			}
   170  		}
   171  	}
   172  	log.Printf("\tids: %#v, randoms: %#v\n", idlist, randList)
   173  
   174  	if err := c.DeleteByPks(ctx, collectionName, "", pks); err != nil {
   175  		log.Fatalf("failed to delete by pks, err: %v", err)
   176  	}
   177  	_, err = c.QueryByPks(ctx, collectionName, nil, pks, []string{randomCol}, client.WithSearchQueryConsistencyLevel(entity.ClStrong))
   178  	if err != nil {
   179  		log.Printf("failed to query result, err: %v", err)
   180  	}
   181  
   182  	// drop collection
   183  	log.Printf(msgFmt, "drop collection `hello_milvus`")
   184  	if err := c.DropCollection(ctx, collectionName); err != nil {
   185  		log.Fatalf("failed to drop collection, err: %v", err)
   186  	}
   187  }
   188  
   189  func printResult(sRet *client.SearchResult) {
   190  	randoms := make([]float64, 0, sRet.ResultCount)
   191  	scores := make([]float32, 0, sRet.ResultCount)
   192  
   193  	var randCol *entity.ColumnDouble
   194  	for _, field := range sRet.Fields {
   195  		if field.Name() == randomCol {
   196  			c, ok := field.(*entity.ColumnDouble)
   197  			if ok {
   198  				randCol = c
   199  			}
   200  		}
   201  	}
   202  	for i := 0; i < sRet.ResultCount; i++ {
   203  		val, err := randCol.ValueByIdx(i)
   204  		if err != nil {
   205  			log.Fatal(err)
   206  		}
   207  		randoms = append(randoms, val)
   208  		scores = append(scores, sRet.Scores[i])
   209  	}
   210  	log.Printf("\trandoms: %v, scores: %v\n", randoms, scores)
   211  }