github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/test/testcases/load_release_test.go (about) 1 //go:build L0 2 3 package testcases 4 5 import ( 6 "fmt" 7 "log" 8 "strconv" 9 "testing" 10 "time" 11 12 "github.com/milvus-io/milvus-sdk-go/v2/client" 13 14 "github.com/milvus-io/milvus-sdk-go/v2/entity" 15 16 "github.com/stretchr/testify/require" 17 18 "github.com/milvus-io/milvus-sdk-go/v2/test/common" 19 ) 20 21 // test load collection 22 func TestLoadCollection(t *testing.T) { 23 //t.Skip("Issue: https://github.com/milvus-io/milvus-sdk-go/issues/374") 24 ctx := createContext(t, time.Second*common.DefaultTimeout) 25 // connect 26 mc := createMilvusClient(ctx, t) 27 28 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true) 29 30 // load two replicas 31 errLoad := mc.LoadCollection(ctx, collName, false) 32 common.CheckErr(t, errLoad, true) 33 34 // check replicas 35 replicas, errReplicas := mc.GetReplicas(ctx, collName) 36 common.CheckErr(t, errReplicas, true) 37 require.Len(t, replicas, 1) 38 39 // check collection loaded 40 collection, _ := mc.DescribeCollection(ctx, collName) 41 log.Println(collection.Loaded) 42 //require.True(t, collection.Loaded) 43 } 44 45 // test load not existed collection 46 func TestLoadCollectionNotExist(t *testing.T) { 47 ctx := createContext(t, time.Second*common.DefaultTimeout) 48 // connect 49 mc := createMilvusClient(ctx, t) 50 51 // Load collection 52 errLoad := mc.LoadCollection(ctx, "collName", false) 53 common.CheckErr(t, errLoad, false, "exist") 54 } 55 56 // test load collection async 57 func TestLoadCollectionAsync(t *testing.T) { 58 t.Skip("Issue: https://github.com/milvus-io/milvus-sdk-go/issues/374") 59 ctx := createContext(t, time.Second*common.DefaultTimeout) 60 // connect 61 mc := createMilvusClient(ctx, t) 62 63 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true) 64 65 // load collection async 66 errLoad := mc.LoadCollection(ctx, collName, true) 67 common.CheckErr(t, errLoad, true) 68 69 for { 70 time.Sleep(2 * time.Second) 71 72 // describe collection 73 collection, errDescribe := mc.DescribeCollection(ctx, collName) 74 if errDescribe == nil { 75 if collection.Loaded { 76 break 77 } 78 } else { 79 t.FailNow() 80 } 81 } 82 } 83 84 // load collection without index 85 func TestLoadCollectionWithoutIndex(t *testing.T) { 86 ctx := createContext(t, time.Second*common.DefaultTimeout) 87 // connect 88 mc := createMilvusClient(ctx, t) 89 90 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, false) 91 errLoad := mc.LoadCollection(ctx, collName, true) 92 common.CheckErr(t, errLoad, false, "index not found") 93 94 // load partitions without index 95 errLoadPartition := mc.LoadPartitions(ctx, collName, []string{common.DefaultPartition}, true) 96 common.CheckErr(t, errLoadPartition, false, "index not found") 97 } 98 99 // load collection with multi partitions 100 func TestLoadCollectionMultiPartitions(t *testing.T) { 101 //t.Skip("Issue: https://github.com/milvus-io/milvus-sdk-go/issues/374") 102 ctx := createContext(t, time.Second*common.DefaultTimeout*3) 103 // connect 104 mc := createMilvusClient(ctx, t) 105 106 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 107 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 108 createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 109 110 // create index 111 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 112 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 113 114 // load partition 115 errLoad := mc.LoadCollection(ctx, collName, false) 116 common.CheckErr(t, errLoad, true) 117 118 // check all partitions loaded 119 partitions, _ := mc.ShowPartitions(ctx, collName) 120 for _, partition := range partitions { 121 log.Println(partition.Loaded) 122 //require.True(t, partition.Loaded) 123 } 124 125 // check collection loaded 126 collection, _ := mc.DescribeCollection(ctx, collName) 127 log.Println(collection.Loaded) 128 //require.True(t, collection.Loaded) 129 } 130 131 // test load with empty partition name "" 132 func TestLoadEmptyPartitionName(t *testing.T) { 133 //t.Skip("Issue: https://github.com/milvus-io/milvus-sdk-go/issues/373") 134 ctx := createContext(t, time.Second*common.DefaultTimeout*3) 135 // connect 136 mc := createMilvusClient(ctx, t) 137 138 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 139 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 140 createInsertTwoPartitions(ctx, t, mc, collName, 500) 141 142 // create index 143 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 144 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 145 146 // load partition with empty partition names 147 errLoadEmpty := mc.LoadPartitions(ctx, collName, []string{""}, false) 148 common.CheckErr(t, errLoadEmpty, false, "request failed") 149 } 150 151 // test load partitions with empty slice []string{} 152 func TestLoadEmptyPartitionSlice(t *testing.T) { 153 ctx := createContext(t, time.Second*common.DefaultTimeout*3) 154 // connect 155 mc := createMilvusClient(ctx, t) 156 157 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 158 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 159 createInsertTwoPartitions(ctx, t, mc, collName, 500) 160 161 // create index 162 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 163 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 164 165 // load partition with empty partition names 166 errLoadEmpty := mc.LoadPartitions(ctx, collName, []string{}, false) 167 common.CheckErr(t, errLoadEmpty, false, "due to no partition specified") 168 } 169 170 // test load partitions not exist 171 func TestLoadPartitionsNotExist(t *testing.T) { 172 ctx := createContext(t, time.Second*common.DefaultTimeout*3) 173 // connect 174 mc := createMilvusClient(ctx, t) 175 176 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 177 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 178 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, 500) 179 180 // create index 181 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 182 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 183 184 // load with not exist partition names 185 errLoadNotExist := mc.LoadPartitions(ctx, collName, []string{"xxx"}, false) 186 common.CheckErr(t, errLoadNotExist, false, fmt.Sprintf("partition xxx of collection %s does not exist", collName)) 187 188 // load partition with part exist partition names 189 errLoadPartExist := mc.LoadPartitions(ctx, collName, []string{"xxx", partitionName}, false) 190 common.CheckErr(t, errLoadPartExist, false, fmt.Sprintf("partition xxx of collection %s does not exist", collName)) 191 } 192 193 // test load partition 194 func TestLoadPartitions(t *testing.T) { 195 ctx := createContext(t, time.Second*common.DefaultTimeout*3) 196 // connect 197 mc := createMilvusClient(ctx, t) 198 199 nb := 1000 200 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 201 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 202 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, nb) 203 204 // create index 205 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 206 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 207 208 // load partition 209 errLoad := mc.LoadPartitions(ctx, collName, []string{partitionName}, false) 210 common.CheckErr(t, errLoad, true) 211 212 // check collection loaded false 213 collection, _ := mc.DescribeCollection(ctx, collName) 214 require.False(t, collection.Loaded) 215 216 partitions, _ := mc.ShowPartitions(ctx, collName) 217 for _, p := range partitions { 218 if p.Name == partitionName { 219 //require.True(t, p.Loaded) 220 log.Println(p.Loaded) 221 } else { 222 log.Println(p.Loaded) 223 //require.True(t, p.Loaded) 224 } 225 log.Printf("id: %d, name: %s, loaded %t", p.ID, p.Name, p.Loaded) 226 } 227 228 //query from nb from partition 229 queryIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0, int64(nb)}) 230 queryResultPartition, _ := mc.QueryByPks(ctx, collName, []string{}, queryIds, []string{common.DefaultIntFieldName}) 231 common.CheckQueryResult(t, queryResultPartition, []entity.Column{ 232 entity.NewColumnInt64(common.DefaultIntFieldName, []int64{int64(nb)}), 233 }) 234 } 235 236 // test load multi partition 237 func TestLoadMultiPartitions(t *testing.T) { 238 ctx := createContext(t, time.Second*common.DefaultTimeout) 239 // connect 240 mc := createMilvusClient(ctx, t) 241 242 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 243 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 244 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 245 246 // create index 247 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 248 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 249 250 // load partition 251 errLoad := mc.LoadPartitions(ctx, collName, []string{partitionName, common.DefaultPartition}, false) 252 common.CheckErr(t, errLoad, true) 253 254 //query nb from partition 255 queryIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0, common.DefaultNb}) 256 queryResultPartition, _ := mc.QueryByPks(ctx, collName, []string{}, queryIds, []string{common.DefaultIntFieldName}) 257 common.CheckQueryResult(t, queryResultPartition, []entity.Column{ 258 entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0, common.DefaultNb}), 259 }) 260 } 261 262 // test load partitions repeatedly 263 func TestLoadPartitionsRepeatedly(t *testing.T) { 264 ctx := createContext(t, time.Second*common.DefaultTimeout*3) 265 // connect 266 mc := createMilvusClient(ctx, t) 267 268 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 269 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 270 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 271 272 // create index 273 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 274 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 275 276 // load repeated partition names 277 errLoadRepeat := mc.LoadPartitions(ctx, collName, []string{partitionName, partitionName}, false) 278 common.CheckErr(t, errLoadRepeat, true) 279 280 //query from nb from partition 281 queryIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{common.DefaultNb}) 282 queryResultPartition, _ := mc.QueryByPks(ctx, collName, []string{}, queryIds, []string{common.DefaultIntFieldName}) 283 common.CheckQueryResult(t, queryResultPartition, []entity.Column{queryIds}) 284 } 285 286 // test load partitions async 287 func TestLoadPartitionsAsync(t *testing.T) { 288 t.Skipf("Issue: https://github.com/milvus-io/milvus-sdk-go/issues/374") 289 ctx := createContext(t, time.Second*common.DefaultTimeout) 290 // connect 291 mc := createMilvusClient(ctx, t) 292 293 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 294 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 295 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 296 297 // create index 298 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 299 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 300 301 // load partitions async 302 errLoad := mc.LoadPartitions(ctx, collName, []string{partitionName}, true) 303 common.CheckErr(t, errLoad, true) 304 305 // check load results 306 for { 307 time.Sleep(time.Second * 5) 308 309 // check partition loaded 310 partitions, errShow := mc.ShowPartitions(ctx, collName) 311 if errShow == nil { 312 for _, p := range partitions { 313 log.Printf("id: %d, name: %s, loaded %t", p.ID, p.Name, p.Loaded) 314 if p.Name == partitionName && p.Loaded { 315 break 316 } 317 } 318 } else { 319 t.FailNow() 320 } 321 } 322 } 323 324 func TestLoadCollectionMultiVectors(t *testing.T) { 325 ctx := createContext(t, time.Second*common.DefaultTimeout*5) 326 // connect 327 mc := createMilvusClient(ctx, t) 328 329 // create collection 330 cp := CollectionParams{CollectionFieldsType: AllVectors, AutoID: false, EnableDynamicField: true, 331 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 332 collName := createCollection(ctx, t, mc, cp) 333 334 // insert 335 dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: AllVectors, 336 start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false} 337 _, _ = insertData(ctx, t, mc, dp) 338 mc.Flush(ctx, collName, false) 339 340 // create hnsw index on part vector field and load -> load failed 341 indexHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 342 for _, field := range []string{common.DefaultFloatVecFieldName, common.DefaultFloat16VecFieldName, common.DefaultBFloat16VecFieldName} { 343 err := mc.CreateIndex(ctx, collName, field, indexHnsw, false) 344 common.CheckErr(t, err, true) 345 } 346 347 err := mc.LoadCollection(ctx, collName, false) 348 common.CheckErr(t, err, false, "there is no vector index on field") 349 350 // create index for another vector field 351 indexBinary, _ := entity.NewIndexBinIvfFlat(entity.JACCARD, 64) 352 for _, field := range []string{common.DefaultBinaryVecFieldName} { 353 err := mc.CreateIndex(ctx, collName, field, indexBinary, false) 354 common.CheckErr(t, err, true) 355 } 356 err = mc.LoadCollection(ctx, collName, false) 357 common.CheckErr(t, err, true) 358 } 359 360 // test release partition 361 func TestReleasePartition(t *testing.T) { 362 ctx := createContext(t, time.Second*common.DefaultTimeout) 363 // connect 364 mc := createMilvusClient(ctx, t) 365 366 // create collection -> insert data -> create index 367 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true) 368 369 //load collection 370 errLoad := mc.LoadCollection(ctx, collName, true) 371 common.CheckErr(t, errLoad, true) 372 373 // release collection 374 errRelease := mc.ReleaseCollection(ctx, collName) 375 common.CheckErr(t, errRelease, true) 376 377 // check collection loaded 378 collection, _ := mc.DescribeCollection(ctx, collName) 379 require.False(t, collection.Loaded) 380 381 // check release success 382 _, errQuery := mc.QueryByPks(ctx, collName, []string{}, entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0}), 383 []string{common.DefaultIntFieldName}) 384 // TODO change error msg or code 385 common.CheckErr(t, errQuery, false, "not loaded") 386 } 387 388 // test release not exist collection 389 func TestReleaseCollectionNotExist(t *testing.T) { 390 ctx := createContext(t, time.Second*common.DefaultTimeout) 391 // connect 392 mc := createMilvusClient(ctx, t) 393 394 // create collection -> insert data -> create index 395 collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true) 396 397 //load collection 398 errLoad := mc.LoadCollection(ctx, collName, true) 399 common.CheckErr(t, errLoad, true) 400 401 // release collection 402 errRelease := mc.ReleaseCollection(ctx, "collName") 403 common.CheckErr(t, errRelease, false, "not exist") 404 } 405 406 // test release partitions 407 func TestReleasePartitions(t *testing.T) { 408 ctx := createContext(t, time.Second*common.DefaultTimeout) 409 // connect 410 mc := createMilvusClient(ctx, t) 411 412 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 413 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 414 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 415 416 // create index 417 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 418 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 419 420 // load partitions async 421 errLoad := mc.LoadPartitions(ctx, collName, []string{partitionName}, true) 422 common.CheckErr(t, errLoad, true) 423 424 // release partition 425 errRelease := mc.ReleasePartitions(ctx, collName, []string{partitionName}) 426 common.CheckErr(t, errRelease, true) 427 428 // check release success 429 partitions, _ := mc.ShowPartitions(ctx, collName) 430 for _, p := range partitions { 431 if p.Name == partitionName { 432 require.False(t, p.Loaded) 433 } 434 } 435 436 // check release success 437 _, errQuery := mc.QueryByPks(ctx, collName, []string{partitionName}, entity.NewColumnInt64(common.DefaultIntFieldName, []int64{common.DefaultNb}), 438 []string{common.DefaultIntFieldName}) 439 440 // TODO fix error msg or code 441 common.CheckErr(t, errQuery, false, "not loaded") 442 } 443 444 // test release partition not exist -> error or part exist -> success 445 func TestReleasePartitionsNotExist(t *testing.T) { 446 ctx := createContext(t, time.Second*common.DefaultTimeout) 447 // connect 448 mc := createMilvusClient(ctx, t) 449 450 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 451 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 452 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 453 454 // create index 455 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 456 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 457 458 // load partitions 459 errLoad := mc.LoadPartitions(ctx, collName, []string{partitionName}, false) 460 common.CheckErr(t, errLoad, true) 461 462 // release partition 463 errRelease := mc.ReleasePartitions(ctx, collName, []string{"partitionName"}) 464 common.CheckErr(t, errRelease, false, "not exist") 465 466 // release partition 467 errRelease2 := mc.ReleasePartitions(ctx, collName, []string{"partitionName", partitionName}) 468 common.CheckErr(t, errRelease2, false, "not exist") 469 470 // check release success 471 partitions, _ := mc.ShowPartitions(ctx, collName) 472 for _, p := range partitions { 473 if p.Name == partitionName { 474 require.False(t, p.Loaded) 475 } 476 } 477 478 // check release success 479 queryIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{common.DefaultNb}) 480 _, errQuery := mc.QueryByPks(ctx, collName, []string{partitionName}, queryIds, 481 []string{common.DefaultIntFieldName}) 482 common.CheckErr(t, errQuery, true) 483 } 484 485 func TestReleaseMultiPartitions(t *testing.T) { 486 ctx := createContext(t, time.Second*common.DefaultTimeout) 487 // connect 488 mc := createMilvusClient(ctx, t) 489 490 // create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition 491 collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards) 492 partitionName, _, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb) 493 494 // create index 495 idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 496 mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false) 497 498 // load multi partitions 499 errLoad := mc.LoadPartitions(ctx, collName, []string{partitionName, common.DefaultPartition}, false) 500 common.CheckErr(t, errLoad, true) 501 502 // release partition 503 errRelease := mc.ReleasePartitions(ctx, collName, []string{partitionName, common.DefaultPartition}) 504 common.CheckErr(t, errRelease, true) 505 506 // check release success 507 partitions, _ := mc.ShowPartitions(ctx, collName) 508 for _, p := range partitions { 509 require.False(t, p.Loaded) 510 } 511 512 // check release success 513 queryIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0, common.DefaultNb}) 514 _, errQuery := mc.QueryByPks(ctx, collName, []string{partitionName, common.DefaultPartition}, queryIds, 515 []string{common.DefaultIntFieldName}) 516 common.CheckErr(t, errQuery, false, "collection not loaded") 517 } 518 519 // test mmap collection raw data and index 520 // create -> insert -> flush -> index with mmap -> load -> alter collection with mmap -> reload -> read op 521 func TestMmapCollectionIndexDefault(t *testing.T) { 522 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 523 // connect 524 mc := createMilvusClient(ctx, t) 525 526 // create -> insert [0, 3000) -> flush 527 cp := CollectionParams{CollectionFieldsType: AllFields, AutoID: false, EnableDynamicField: true, 528 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 529 collName := createCollection(ctx, t, mc, cp) 530 531 dp := DataParams{DoInsert: true, CollectionName: collName, CollectionFieldsType: AllFields, start: 0, 532 nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true} 533 insertData(ctx, t, mc, dp) 534 _ = mc.Flush(ctx, collName, false) 535 536 // create vector index with mmap 537 GenDefaultIndexParamsForAllVectors() 538 indexHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 539 indexBinary, _ := entity.NewIndexBinIvfFlat(entity.JACCARD, 64) 540 for _, fieldName := range common.AllVectorsFieldsName { 541 if fieldName == common.DefaultBinaryVecFieldName { 542 err := mc.CreateIndex(ctx, collName, fieldName, indexBinary, false, client.WithMmap(true)) 543 common.CheckErr(t, err, true) 544 } else if fieldName == common.DefaultFloatVecFieldName { 545 err := mc.CreateIndex(ctx, collName, fieldName, indexHnsw, false, client.WithMmap(true)) 546 common.CheckErr(t, err, true) 547 } else { 548 err := mc.CreateIndex(ctx, collName, fieldName, indexHnsw, false) 549 common.CheckErr(t, err, true) 550 } 551 } 552 553 // describe index and check mmap 554 for _, fieldName := range common.AllVectorsFieldsName { 555 if fieldName == common.DefaultFloatVecFieldName || fieldName == common.DefaultBinaryVecFieldName { 556 indexes, _ := mc.DescribeIndex(ctx, collName, fieldName) 557 require.Len(t, indexes, 1) 558 // check index mmap 559 require.Equal(t, "true", indexes[0].Params()["mmap.enabled"]) 560 } 561 } 562 563 // load collection -> describe collection and check mmap false 564 _ = mc.LoadCollection(ctx, collName, false) 565 coll, _ := mc.DescribeCollection(ctx, collName) 566 require.Equal(t, "", coll.Properties["mmap.enabled"]) 567 568 // alter collection and check collection mmap 569 _ = mc.ReleaseCollection(ctx, collName) 570 err := mc.AlterCollection(ctx, collName, entity.Mmap(true)) 571 common.CheckErr(t, err, true) 572 573 //describe collection 574 mc.LoadCollection(ctx, collName, false) 575 coll, _ = mc.DescribeCollection(ctx, collName) 576 require.Equal(t, "true", coll.Properties["mmap.enabled"]) 577 578 // query 579 queryRes, err := mc.Query(ctx, collName, []string{}, fmt.Sprintf("%s < 10", common.DefaultIntFieldName), []string{"*"}) 580 common.CheckErr(t, err, true) 581 require.Equal(t, queryRes.GetColumn(common.DefaultIntFieldName).Len(), 10) 582 common.CheckOutputFields(t, queryRes, common.GetAllFieldsName(true, false)) 583 584 // search 585 queryVec1 := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector) 586 sp, _ := entity.NewIndexHNSWSearchParam(74) 587 expr := fmt.Sprintf("%s > 10", common.DefaultIntFieldName) 588 searchRes, _ := mc.Search(ctx, collName, []string{}, expr, []string{"*"}, queryVec1, common.DefaultFloatVecFieldName, 589 entity.L2, common.DefaultTopK, sp) 590 common.CheckOutputFields(t, searchRes[0].Fields, common.GetAllFieldsName(true, false)) 591 592 // hybrid search 593 queryVec2 := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector) 594 sReqs := []*client.ANNSearchRequest{ 595 client.NewANNSearchRequest(common.DefaultFloatVecFieldName, entity.L2, "", queryVec1, sp, common.DefaultTopK, client.WithOffset(3)), 596 client.NewANNSearchRequest(common.DefaultBinaryVecFieldName, entity.JACCARD, "", queryVec2, sp, common.DefaultTopK), 597 } 598 _, errSearch := mc.HybridSearch(ctx, collName, []string{}, common.DefaultTopK, []string{}, client.NewRRFReranker(), sReqs) 599 common.CheckErr(t, errSearch, true) 600 } 601 602 // test mmap collection raw data and index 603 // create -> insert -> flush -> index -> load -> alter collection with mmap -> alter index with mmap -> reload -> read op 604 func TestMmapAlterCollectionIndexDefault(t *testing.T) { 605 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 606 // connect 607 mc := createMilvusClient(ctx, t) 608 609 // create -> insert [0, 3000) -> flush 610 cp := CollectionParams{CollectionFieldsType: AllFields, AutoID: false, EnableDynamicField: true, 611 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 612 613 dp := DataParams{DoInsert: true, CollectionFieldsType: AllFields, start: 0, 614 nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true} 615 616 ips := GenDefaultIndexParamsForAllVectors() 617 collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong))) 618 619 // describe index and check mmap 620 for _, fieldName := range common.AllVectorsFieldsName { 621 indexes, _ := mc.DescribeIndex(ctx, collName, fieldName) 622 // check index mmap 623 require.Equal(t, "", indexes[0].Params()["mmap.enabled"]) 624 } 625 626 //describe collection 627 mc.LoadCollection(ctx, collName, false) 628 coll, _ := mc.DescribeCollection(ctx, collName) 629 require.Equal(t, "", coll.Properties["mmap.enabled"]) 630 631 // alter mmap: collection and index 632 _ = mc.ReleaseCollection(ctx, collName) 633 err := mc.AlterCollection(ctx, collName, entity.Mmap(true)) 634 common.CheckErr(t, err, true) 635 for _, fieldName := range common.AllVectorsFieldsName { 636 err := mc.AlterIndex(ctx, collName, fieldName, client.WithMmap(true)) 637 common.CheckErr(t, err, true) 638 } 639 640 // load collection -> describe collection and check mmap false 641 //describe collection 642 mc.LoadCollection(ctx, collName, false) 643 coll, _ = mc.DescribeCollection(ctx, collName) 644 require.Equal(t, "true", coll.Properties["mmap.enabled"]) 645 for _, fieldName := range common.AllVectorsFieldsName { 646 idx, _ := mc.DescribeIndex(ctx, collName, fieldName) 647 require.Equal(t, "true", idx[0].Params()["mmap.enabled"]) 648 } 649 650 // query 651 queryRes, err := mc.Query(ctx, collName, []string{}, fmt.Sprintf("%s < 10", common.DefaultIntFieldName), []string{"*"}) 652 common.CheckErr(t, err, true) 653 require.Equal(t, queryRes.GetColumn(common.DefaultIntFieldName).Len(), 10) 654 common.CheckOutputFields(t, queryRes, common.GetAllFieldsName(true, false)) 655 656 // search 657 queryVec1 := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector) 658 sp, _ := entity.NewIndexHNSWSearchParam(74) 659 expr := fmt.Sprintf("%s > 10", common.DefaultIntFieldName) 660 searchRes, _ := mc.Search(ctx, collName, []string{}, expr, []string{"*"}, queryVec1, common.DefaultFloatVecFieldName, 661 entity.L2, common.DefaultTopK, sp) 662 common.CheckOutputFields(t, searchRes[0].Fields, common.GetAllFieldsName(true, false)) 663 664 // hybrid search 665 queryVec2 := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeBinaryVector) 666 sReqs := []*client.ANNSearchRequest{ 667 client.NewANNSearchRequest(common.DefaultFloatVecFieldName, entity.L2, "", queryVec1, sp, common.DefaultTopK, client.WithOffset(3)), 668 client.NewANNSearchRequest(common.DefaultBinaryVecFieldName, entity.JACCARD, "", queryVec2, sp, common.DefaultTopK), 669 } 670 _, errSearch := mc.HybridSearch(ctx, collName, []string{}, common.DefaultTopK, []string{}, client.NewRRFReranker(), sReqs) 671 common.CheckErr(t, errSearch, true) 672 } 673 674 // test mmap collection loaded 675 func TestMmapCollectionLoaded(t *testing.T) { 676 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 677 // connect 678 mc := createMilvusClient(ctx, t) 679 680 // create -> insert -> flush -> index -> load 681 cp := CollectionParams{CollectionFieldsType: Int64FloatVec, AutoID: false, EnableDynamicField: false, 682 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 683 684 dp := DataParams{DoInsert: true, CollectionFieldsType: Int64FloatVec, start: 0, nb: common.DefaultNb, 685 dim: common.DefaultDim, EnableDynamicField: false} 686 687 collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong))) 688 689 // mmap collection raw data 690 err := mc.AlterCollection(ctx, collName, entity.Mmap(true)) 691 common.CheckErr(t, err, false, "can not alter mmap properties if collection loaded") 692 693 // mmap index 694 err = mc.AlterIndex(ctx, collName, common.DefaultFloatVecFieldName, client.WithMmap(true)) 695 common.CheckErr(t, err, false, "can't alter index on loaded collection, please release the collection first") 696 } 697 698 // test mmap collection which scalar field indexed 699 func TestMmapCollectionScalarIndexed(t *testing.T) { 700 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 701 // connect 702 mc := createMilvusClient(ctx, t) 703 704 // create -> insert -> flush -> index -> load 705 cp := CollectionParams{CollectionFieldsType: Int64FloatVec, AutoID: false, EnableDynamicField: false, 706 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 707 708 dp := DataParams{DoInsert: true, CollectionFieldsType: Int64FloatVec, start: 0, nb: common.DefaultNb, 709 dim: common.DefaultDim, EnableDynamicField: false} 710 711 collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong))) 712 713 // create scalar index 714 for _, fName := range []string{common.DefaultIntFieldName, common.DefaultFloatFieldName} { 715 err := mc.CreateIndex(ctx, collName, fName, entity.NewScalarIndexWithType(entity.Inverted), false) 716 common.CheckErr(t, err, true) 717 } 718 719 // mmap collection 720 mc.ReleaseCollection(ctx, collName) 721 err := mc.AlterCollection(ctx, collName, entity.Mmap(true)) 722 common.CheckErr(t, err, true) 723 err = mc.LoadCollection(ctx, collName, false) 724 common.CheckErr(t, err, true) 725 } 726 727 // test mmap unsupported index: DiskANN, GPU-class 728 func TestMmapIndexUnsupported(t *testing.T) { 729 t.Skip("https://github.com/milvus-io/milvus-sdk-go/issues/714") 730 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 731 // connect 732 mc := createMilvusClient(ctx, t) 733 734 // create -> insert -> flush -> index -> load 735 cp := CollectionParams{CollectionFieldsType: Int64FloatVec, AutoID: false, EnableDynamicField: false, 736 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 737 collName := createCollection(ctx, t, mc, cp) 738 739 dp := DataParams{DoInsert: true, CollectionName: collName, CollectionFieldsType: Int64FloatVec, start: 0, 740 nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: false} 741 insertData(ctx, t, mc, dp) 742 mc.Flush(ctx, collName, false) 743 744 //create index with mmap 745 idx, _ := entity.NewIndexDISKANN(entity.COSINE) 746 err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false, client.WithMmap(true)) 747 common.CheckErr(t, err, false, "index type DISKANN does not support mmap") 748 749 //create scalar index with mmap 750 for _, idx := range []entity.Index{entity.NewScalarIndex(), entity.NewScalarIndexWithType(entity.Inverted)} { 751 err := mc.CreateIndex(ctx, collName, common.DefaultFloatFieldName, idx, false, client.WithMmap(true)) 752 common.CheckErr(t, err, false, "does not support mmap") 753 } 754 } 755 756 func TestAlterIndexMmapUnsupportedIndex(t *testing.T) { 757 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 758 // connect 759 mc := createMilvusClient(ctx, t) 760 761 // create -> insert -> flush -> index -> load 762 cp := CollectionParams{CollectionFieldsType: Int64FloatVec, AutoID: false, EnableDynamicField: false, 763 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 764 collName := createCollection(ctx, t, mc, cp) 765 766 dp := DataParams{DoInsert: true, CollectionName: collName, CollectionFieldsType: Int64FloatVec, start: 0, 767 nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: false} 768 insertData(ctx, t, mc, dp) 769 mc.Flush(ctx, collName, false) 770 771 idxHnsw, _ := entity.NewIndexDISKANN(entity.IP) 772 err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idxHnsw, false) 773 common.CheckErr(t, err, true) 774 for _, mmap := range []bool{true, false} { 775 err = mc.AlterIndex(ctx, collName, common.DefaultFloatVecFieldName, client.WithMmap(mmap)) 776 common.CheckErr(t, err, false, "index type DISKANN does not support mmap: invalid parameter") 777 } 778 } 779 780 func TestMmapAlterIndex(t *testing.T) { 781 t.Parallel() 782 for _, mmap := range []bool{true, false} { 783 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 784 // connect 785 mc := createMilvusClient(ctx, t) 786 787 // create -> insert -> flush -> index -> load 788 cp := CollectionParams{CollectionFieldsType: Int64FloatVec, AutoID: false, EnableDynamicField: false, 789 ShardsNum: common.DefaultShards, Dim: common.DefaultDim} 790 collName := createCollection(ctx, t, mc, cp) 791 792 dp := DataParams{DoInsert: true, CollectionName: collName, CollectionFieldsType: Int64FloatVec, start: 0, 793 nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: false} 794 insertData(ctx, t, mc, dp) 795 mc.Flush(ctx, collName, false) 796 797 // create index and enable mmap 798 idxHnsw, _ := entity.NewIndexHNSW(entity.COSINE, 8, 96) 799 err := mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idxHnsw, false, client.WithMmap(!mmap)) 800 common.CheckErr(t, err, true) 801 802 // alter index and enable mmap 803 err = mc.AlterIndex(ctx, collName, common.DefaultFloatVecFieldName, client.WithMmap(mmap)) 804 common.CheckErr(t, err, true) 805 806 idx, _ := mc.DescribeIndex(ctx, collName, common.DefaultFloatVecFieldName) 807 require.Equal(t, strconv.FormatBool(mmap), idx[0].Params()["mmap.enabled"]) 808 809 err = mc.LoadCollection(ctx, collName, false) 810 common.CheckErr(t, err, true) 811 812 queryVec1 := common.GenSearchVectors(common.DefaultNq, common.DefaultDim, entity.FieldTypeFloatVector) 813 sp, _ := entity.NewIndexHNSWSearchParam(74) 814 expr := fmt.Sprintf("%s > 10", common.DefaultIntFieldName) 815 searchRes, _ := mc.Search(ctx, collName, []string{}, expr, []string{"*"}, queryVec1, common.DefaultFloatVecFieldName, 816 entity.COSINE, common.DefaultTopK, sp) 817 common.CheckOutputFields(t, searchRes[0].Fields, []string{common.DefaultIntFieldName, common.DefaultFloatFieldName, common.DefaultFloatVecFieldName}) 818 } 819 } 820 821 // test search when mmap sparse collection 822 func TestMmapSparseCollection(t *testing.T) { 823 t.Skip("sparse index support mmap now") 824 t.Parallel() 825 idxInverted, _ := entity.NewIndexSparseInverted(entity.IP, 0) 826 idxWand, _ := entity.NewIndexSparseWAND(entity.IP, 0) 827 for _, idx := range []entity.Index{idxInverted, idxWand} { 828 ctx := createContext(t, time.Second*common.DefaultTimeout*2) 829 // connect 830 mc := createMilvusClient(ctx, t) 831 832 // create -> insert [0, 3000) -> flush -> index -> load 833 cp := CollectionParams{CollectionFieldsType: Int64VarcharSparseVec, AutoID: false, EnableDynamicField: true, 834 ShardsNum: common.DefaultShards, Dim: common.DefaultDim, MaxLength: common.TestMaxLen} 835 836 dp := DataParams{DoInsert: true, CollectionFieldsType: Int64VarcharSparseVec, start: 0, nb: common.DefaultNb * 5, 837 dim: common.DefaultDim, EnableDynamicField: true} 838 839 // index params 840 idxHnsw, _ := entity.NewIndexHNSW(entity.L2, 8, 96) 841 ips := []IndexParams{ 842 {BuildIndex: true, Index: idx, FieldName: common.DefaultSparseVecFieldName, async: false}, 843 {BuildIndex: true, Index: idxHnsw, FieldName: common.DefaultFloatVecFieldName, async: false}, 844 } 845 collName := prepareCollection(ctx, t, mc, cp, WithDataParams(dp), WithIndexParams(ips), WithCreateOption(client.WithConsistencyLevel(entity.ClStrong))) 846 847 // alter mmap 848 mc.ReleaseCollection(ctx, collName) 849 // alter index and enable mmap 850 err := mc.AlterIndex(ctx, collName, common.DefaultSparseVecFieldName, client.WithMmap(true)) 851 common.CheckErr(t, err, false, fmt.Sprintf("index type %s does not support mmap", idx.IndexType())) 852 err = mc.AlterIndex(ctx, collName, common.DefaultFloatVecFieldName, client.WithMmap(true)) 853 common.CheckErr(t, err, true) 854 err = mc.AlterCollection(ctx, collName, entity.Mmap(true)) 855 common.CheckErr(t, err, true) 856 err = mc.LoadCollection(ctx, collName, false) 857 common.CheckErr(t, err, true) 858 859 // search with floatVec field 860 outputFields := []string{common.DefaultIntFieldName, common.DefaultVarcharFieldName, common.DefaultFloatVecFieldName, 861 common.DefaultSparseVecFieldName, common.DefaultDynamicFieldName} 862 queryVecFloat := common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeFloatVector) 863 sp, _ := entity.NewIndexSparseInvertedSearchParam(0) 864 resSearch, errSearch := mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVecFloat, common.DefaultFloatVecFieldName, 865 entity.L2, common.DefaultTopK, sp) 866 common.CheckErr(t, errSearch, true) 867 common.CheckSearchResult(t, resSearch, 1, common.DefaultTopK) 868 common.CheckOutputFields(t, resSearch[0].Fields, outputFields) 869 870 // search with sparse vector field 871 queryVecSparse := common.GenSearchVectors(1, common.DefaultDim, entity.FieldTypeSparseVector) 872 resSearch, errSearch = mc.Search(ctx, collName, []string{}, "", []string{"*"}, queryVecSparse, common.DefaultSparseVecFieldName, 873 entity.IP, common.DefaultTopK, sp) 874 common.CheckErr(t, errSearch, true) 875 common.CheckSearchResult(t, resSearch, 1, common.DefaultTopK) 876 common.CheckOutputFields(t, resSearch[0].Fields, outputFields) 877 } 878 }