github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/examples/calcdistance/calc_distance.go (about) 1 package main 2 3 import ( 4 "context" 5 "encoding/csv" 6 "log" 7 "os" 8 "strconv" 9 "strings" 10 "time" 11 12 "github.com/milvus-io/milvus-sdk-go/v2/client" 13 "github.com/milvus-io/milvus-sdk-go/v2/entity" 14 ) 15 16 func main() { 17 // Milvus instance proxy address, may verify in your env/settings 18 milvusAddr := `localhost:19530` 19 20 // setup context for client creation, use 2 seconds here 21 ctx := context.Background() 22 ctx, cancel := context.WithTimeout(ctx, 2*time.Second) 23 defer cancel() 24 25 c, err := client.NewClient(ctx, client.Config{ 26 Address: milvusAddr, 27 }) 28 if err != nil { 29 // handling error and exit, to make example simple here 30 log.Fatal("failed to connect to milvus:", err.Error()) 31 } 32 // in a main func, remember to close the client 33 defer c.Close() 34 35 // here is the collection name we use in this example 36 collectionName := `gosdk_insert_example` 37 38 has, err := c.HasCollection(ctx, collectionName) 39 if err != nil { 40 log.Fatal("failed to check whether collection exists:", err.Error()) 41 } 42 if has { 43 // collection with same name exist, clean up mess 44 _ = c.DropCollection(ctx, collectionName) 45 } 46 47 // define collection schema, see film.csv 48 schema := &entity.Schema{ 49 CollectionName: collectionName, 50 Description: "this is the example collection for inser and search", 51 AutoID: false, 52 Fields: []*entity.Field{ 53 { 54 Name: "ID", 55 DataType: entity.FieldTypeInt64, // int64 only for now 56 PrimaryKey: true, 57 AutoID: false, 58 }, 59 { 60 Name: "Year", 61 DataType: entity.FieldTypeInt32, 62 PrimaryKey: false, 63 AutoID: false, 64 }, 65 { 66 Name: "Vector", 67 DataType: entity.FieldTypeFloatVector, 68 TypeParams: map[string]string{ 69 entity.TypeParamDim: "8", 70 }, 71 }, 72 }, 73 } 74 75 err = c.CreateCollection(ctx, schema, entity.DefaultShardNumber) 76 if err != nil { 77 log.Fatal("failed to create collection:", err.Error()) 78 } 79 80 films, err := loadFilmCSV() 81 if err != nil { 82 log.Fatal("failed to load film data csv:", err.Error()) 83 } 84 85 // row-base covert to column-base 86 ids := make([]int64, 0, len(films)) 87 years := make([]int32, 0, len(films)) 88 vectors := make([][]float32, 0, len(films)) 89 // string field is not supported yet 90 idTitle := make(map[int64]string) 91 for idx, film := range films { 92 ids = append(ids, film.ID) 93 idTitle[film.ID] = film.Title 94 years = append(years, film.Year) 95 vectors = append(vectors, films[idx].Vector[:]) // prevent same vector 96 } 97 idColumn := entity.NewColumnInt64("ID", ids) 98 yearColumn := entity.NewColumnInt32("Year", years) 99 vectorColumn := entity.NewColumnFloatVector("Vector", 8, vectors) 100 101 // insert into default partition 102 rids, err := c.Insert(ctx, collectionName, "", idColumn, yearColumn, vectorColumn) 103 if err != nil { 104 log.Fatal("failed to insert film data:", err.Error()) 105 } 106 log.Println("insert completed") 107 ctx, cancel = context.WithTimeout(context.Background(), time.Second*120) 108 defer cancel() 109 err = c.Flush(ctx, collectionName, false) 110 if err != nil { 111 log.Fatal("failed to flush collection:", err.Error()) 112 } 113 log.Println("flush completed") 114 115 // load collection with async=false 116 err = c.LoadCollection(ctx, collectionName, false) 117 if err != nil { 118 log.Fatal("failed to load collection:", err.Error()) 119 } 120 log.Println("load collection completed") 121 122 // searchFilm := films[0] // use first fim to search 123 // vector := entity.FloatVector(searchFilm.Vector[:]) 124 // Use flat search param 125 126 r, err := c.CalcDistance(ctx, collectionName, []string{}, entity.L2, entity.NewColumnFloatVector("Vector", 8, vectors[0:2]), entity.NewColumnFloatVector("Vector", 8, vectors[3:4])) 127 if err != nil { 128 log.Fatal("failed to calc distance:", err.Error()) 129 } 130 rcol, ok := r.(*entity.ColumnFloat) 131 if ok { 132 log.Println("distance", rcol.Data()) 133 } 134 135 ridsColumn, ok := rids.(*entity.ColumnInt64) 136 if !ok { 137 log.Fatal("returned ids not int64 column") 138 } 139 140 r, err = c.CalcDistance(ctx, collectionName, []string{}, entity.L2, entity.NewColumnInt64("Vector", ridsColumn.Data()[0:1]), entity.NewColumnFloatVector("Vector", 8, vectors[3:4])) 141 if err != nil { 142 log.Fatal("failed to calc distance:", err.Error()) 143 } 144 rcol, ok = r.(*entity.ColumnFloat) 145 if ok { 146 log.Println("distance", rcol.Data()) 147 } 148 149 // clean up 150 _ = c.DropCollection(ctx, collectionName) 151 } 152 153 type film struct { 154 ID int64 155 Title string 156 Year int32 157 Vector [8]float32 // fix length array 158 } 159 160 func loadFilmCSV() ([]film, error) { 161 f, err := os.Open("../films.csv") // assume you are in examples/insert folder, if not, please change the path 162 if err != nil { 163 return []film{}, err 164 } 165 r := csv.NewReader(f) 166 raw, err := r.ReadAll() 167 if err != nil { 168 return []film{}, err 169 } 170 films := make([]film, 0, len(raw)) 171 for _, line := range raw { 172 if len(line) < 4 { // insuffcient column 173 continue 174 } 175 fi := film{} 176 // ID 177 v, err := strconv.ParseInt(line[0], 10, 64) 178 if err != nil { 179 continue 180 } 181 fi.ID = v 182 // Title 183 fi.Title = line[1] 184 // Year 185 v, err = strconv.ParseInt(line[2], 10, 64) 186 if err != nil { 187 continue 188 } 189 fi.Year = int32(v) 190 // Vector 191 vectorStr := strings.ReplaceAll(line[3], "[", "") 192 vectorStr = strings.ReplaceAll(vectorStr, "]", "") 193 parts := strings.Split(vectorStr, ",") 194 if len(parts) != 8 { // dim must be 8 195 continue 196 } 197 for idx, part := range parts { 198 part = strings.TrimSpace(part) 199 v, err := strconv.ParseFloat(part, 32) 200 if err != nil { 201 continue 202 } 203 fi.Vector[idx] = float32(v) 204 } 205 films = append(films, fi) 206 } 207 return films, nil 208 }