Explorar o código

Update the index interface to be consistent with pymilvus (#400)

Signed-off-by: cai.zhang <cai.zhang@zilliz.com>

Signed-off-by: cai.zhang <cai.zhang@zilliz.com>
cai.zhang %!s(int64=2) %!d(string=hai) anos
pai
achega
99ef94485c

+ 2 - 2
docker-compose.yml

@@ -31,7 +31,7 @@ services:
 
   standalone:
     container_name: milvus-javasdk-test-standalone
-    image: milvusdb/milvus-dev:2.1.0-latest
+    image: milvusdb/milvus:master-20221103-94aafb50
     command: ["milvus", "run", "standalone"]
     environment:
       ETCD_ENDPOINTS: etcd:2379
@@ -75,7 +75,7 @@ services:
 
   standaloneslave:
     container_name: milvus-javasdk-test-slave-standalone
-    image: milvusdb/milvus-dev:2.1.0-latest
+    image: milvusdb/milvus:master-20221103-94aafb50
     command: ["milvus", "run", "standalone"]
     environment:
       ETCD_ENDPOINTS: etcdslave:2379

+ 26 - 26
src/main/java/io/milvus/client/AbstractMilvusGrpcClient.java

@@ -290,7 +290,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         });
     }
 
-    private R<Boolean> waitForIndex(String collectionName, String indexName,
+    private R<Boolean> waitForIndex(String collectionName, String indexName, String fieldName,
                                     long waitingInterval, long timeout) {
         // This method use getIndexState() to check index state.
         // If all index state become Finished, then we say the sync index action is finished.
@@ -304,16 +304,29 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                 return R.failed(R.Status.UnexpectedError, msg);
             }
 
-            GetIndexStateRequest request = GetIndexStateRequest.newBuilder()
+            DescribeIndexRequest request = DescribeIndexRequest.newBuilder()
                     .setCollectionName(collectionName)
                     .setIndexName(indexName)
                     .build();
 
-            GetIndexStateResponse response = blockingStub().getIndexState(request);
-            if (response.getState() == IndexState.Finished) {
+            DescribeIndexResponse response = blockingStub().describeIndex(request);
+
+            if (response.getStatus().getErrorCode() != ErrorCode.Success) {
+                return R.failed(response.getStatus().getErrorCode(), response.getStatus().getReason());
+            }
+
+            if (response.getIndexDescriptionsList().size() == 0) {
+                return R.failed(R.Status.UnexpectedError, response.getStatus().getReason());
+            }
+            IndexDescription index = response.getIndexDescriptionsList().stream()
+                    .filter(x -> x.getFieldName().equals(fieldName))
+                    .findFirst()
+                    .orElse(response.getIndexDescriptions(0));
+
+            if (index.getState() == IndexState.Finished) {
                 return R.success(true);
-            } else if (response.getState() == IndexState.Failed) {
-                String msg = "Get index state failed: " + response.toString();
+            } else if (index.getState() == IndexState.Failed) {
+                String msg = "Get index state failed: " + index.getState().toString();
                 logError(msg);
                 return R.failed(R.Status.UnexpectedError, msg);
             }
@@ -1051,14 +1064,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                 extraParamList.forEach(createIndexRequestBuilder::addExtraParams);
             }
 
-            // keep consistence behavior with python sdk, if the index type is flat, return succeed with a warning
-            // TODO: call dropIndex if the index type is flat
-            // TODO: call describeCollection to check field name
-            if (requestParam.getIndexName() == "FLAT" || requestParam.getIndexName() == "BIN_FLAT") {
-                return R.success(new RpcStatus("Warning: It is not necessary to build index with index_type: FLAT"));
-            }
-
-            CreateIndexRequest createIndexRequest = createIndexRequestBuilder.setCollectionName(requestParam.getCollectionName())
+            CreateIndexRequest createIndexRequest = createIndexRequestBuilder
+                    .setCollectionName(requestParam.getCollectionName())
                     .setFieldName(requestParam.getFieldName())
                     .setIndexName(requestParam.getIndexName())
                     .build();
@@ -1070,6 +1077,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
             if (requestParam.isSyncMode()) {
                 R<Boolean> res = waitForIndex(requestParam.getCollectionName(), requestParam.getIndexName(),
+                        requestParam.getFieldName(),
                         requestParam.getSyncWaitingInterval(), requestParam.getSyncWaitingTimeout());
                 if (res.getStatus() != R.Status.Success.getCode()) {
                     logError("CreateIndexRequest in sync mode" + " failed:\n{}", res.getMessage());
@@ -1099,21 +1107,9 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         logInfo(requestParam.toString());
 
         try {
-            DescribeIndexRequest describeIndexRequest = DescribeIndexRequest.newBuilder()
-                    .setCollectionName(requestParam.getCollectionName())
-                    .setIndexName(requestParam.getIndexName())
-                    .build();
-
-            DescribeIndexResponse descResp = blockingStub().describeIndex(describeIndexRequest);
-            if (descResp.getStatus().getErrorCode() != ErrorCode.Success || descResp.getIndexDescriptionsCount() == 0) {
-                logError("Index doesn't exist:\n{}", requestParam.getIndexName());
-                return R.failed(R.Status.IndexNotExist, "Index doesn't exist");
-            }
-
             DropIndexRequest dropIndexRequest = DropIndexRequest.newBuilder()
                     .setCollectionName(requestParam.getCollectionName())
                     .setIndexName(requestParam.getIndexName())
-                    .setFieldName(descResp.getIndexDescriptions(0).getFieldName())
                     .build();
 
             Status response = blockingStub().dropIndex(dropIndexRequest);
@@ -1167,6 +1163,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         }
     }
 
+    @Deprecated
+    // use DescribeIndex instead
     @Override
     public R<GetIndexStateResponse> getIndexState(@NonNull GetIndexStateParam requestParam) {
         if (!clientIsReady()) {
@@ -1198,6 +1196,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         }
     }
 
+    @Deprecated
+    // use DescribeIndex instead
     @Override
     public R<GetIndexBuildProgressResponse> getIndexBuildProgress(@NonNull GetIndexBuildProgressParam requestParam) {
         if (!clientIsReady()) {

+ 66 - 1
src/test/java/io/milvus/client/MilvusClientDockerTest.java

@@ -461,6 +461,12 @@ class MilvusClientDockerTest {
         fieldData = results.getFieldData(field4Name, nq - 1);
         assertEquals(topK, fieldData.size());
 
+        // release collection
+        ReleaseCollectionParam releaseCollectionParam = ReleaseCollectionParam.newBuilder()
+                .withCollectionName(randomCollectionName).build();
+        R<RpcStatus> releaseCollectionR = client.releaseCollection(releaseCollectionParam);
+        assertEquals(R.Status.Success.getCode(), releaseCollectionR.getStatus().intValue());
+
         // drop index
         DropIndexParam dropIndexParam = DropIndexParam.newBuilder()
                 .withCollectionName(randomCollectionName)
@@ -543,13 +549,27 @@ class MilvusClientDockerTest {
         GetCollStatResponseWrapper stat = new GetCollStatResponseWrapper(statR.getData());
         System.out.println("Collection row count: " + stat.getRowCount());
 
+        // create index
+        CreateIndexParam indexParam2 = CreateIndexParam.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withFieldName(field2Name)
+                .withIndexType(IndexType.BIN_FLAT)
+                .withMetricType(MetricType.SUPERSTRUCTURE)
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingInterval(500L)
+                .withSyncWaitingTimeout(30L)
+                .build();
+
+        R<RpcStatus> createIndexR2 = client.createIndex(indexParam2);
+        assertEquals(R.Status.Success.getCode(), createIndexR2.getStatus().intValue());
+
         // load collection
         R<RpcStatus> loadR = client.loadCollection(LoadCollectionParam.newBuilder()
                 .withCollectionName(randomCollectionName)
                 .build());
         assertEquals(R.Status.Success.getCode(), loadR.getStatus().intValue());
 
-        // search without index
+        // search with BIN_FLAT index
         List<ByteBuffer> oneVector = new ArrayList<>();
         oneVector.add(vectors.get(0));
 
@@ -569,6 +589,17 @@ class MilvusClientDockerTest {
         System.out.println("The result of " + ids.get(0) + " with SUPERSTRUCTURE metric:");
         System.out.println(oneScores);
 
+        // release collection
+        ReleaseCollectionParam releaseCollectionParam = ReleaseCollectionParam.newBuilder()
+                .withCollectionName(randomCollectionName).build();
+        R<RpcStatus> releaseCollectionR = client.releaseCollection(releaseCollectionParam);
+        assertEquals(R.Status.Success.getCode(), releaseCollectionR.getStatus().intValue());
+
+        DropIndexParam dropIndexParam = DropIndexParam.newBuilder()
+                .withCollectionName(randomCollectionName).build();
+        R<RpcStatus> dropIndexR = client.dropIndex(dropIndexParam);
+        assertEquals(R.Status.Success.getCode(), dropIndexR.getStatus().intValue());
+
         // create index
         CreateIndexParam indexParam = CreateIndexParam.newBuilder()
                 .withCollectionName(randomCollectionName)
@@ -590,6 +621,12 @@ class MilvusClientDockerTest {
         R<DescribeIndexResponse> descIndexR = client.describeIndex(descIndexParam);
         assertEquals(R.Status.Success.getCode(), descIndexR.getStatus().intValue());
 
+        // load collection
+        R<RpcStatus> loadR2 = client.loadCollection(LoadCollectionParam.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .build());
+        assertEquals(R.Status.Success.getCode(), loadR2.getStatus().intValue());
+
         // pick some vectors to search with index
         int nq = 5;
         List<Long> targetVectorIDs = new ArrayList<>();
@@ -709,6 +746,20 @@ class MilvusClientDockerTest {
         GetCollStatResponseWrapper stat = new GetCollStatResponseWrapper(statR.getData());
         System.out.println("Collection row count: " + stat.getRowCount());
 
+        // create index
+        CreateIndexParam indexParam = CreateIndexParam.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withFieldName(field2Name)
+                .withIndexType(IndexType.FLAT)
+                .withMetricType(MetricType.IP)
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingInterval(500L)
+                .withSyncWaitingTimeout(30L)
+                .build();
+
+        R<RpcStatus> createIndexR = client.createIndex(indexParam);
+        assertEquals(R.Status.Success.getCode(), createIndexR.getStatus().intValue());
+
         // load collection
         R<RpcStatus> loadR = client.loadCollection(LoadCollectionParam.newBuilder()
                 .withCollectionName(randomCollectionName)
@@ -957,6 +1008,20 @@ class MilvusClientDockerTest {
         R<DescribeIndexResponse> descIndexR = client.describeIndex(descIndexParam);
         assertEquals(R.Status.Success.getCode(), descIndexR.getStatus().intValue());
 
+        // create index
+        CreateIndexParam indexParam2 = CreateIndexParam.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withFieldName(field2Name)
+                .withIndexType(IndexType.FLAT)
+                .withMetricType(MetricType.IP)
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingInterval(500L)
+                .withSyncWaitingTimeout(30L)
+                .build();
+
+        R<RpcStatus> createIndexR2 = client.createIndex(indexParam2);
+        assertEquals(R.Status.Success.getCode(), createIndexR2.getStatus().intValue());
+
         // load collection
         R<RpcStatus> loadR = client.loadCollection(LoadCollectionParam.newBuilder()
                 .withCollectionName(randomCollectionName)

+ 28 - 0
src/test/java/io/milvus/client/MilvusMultiClientDockerTest.java

@@ -531,6 +531,20 @@ class MilvusMultiClientDockerTest {
         GetCollStatResponseWrapper stat = new GetCollStatResponseWrapper(statR.getData());
         System.out.println("Collection row count: " + stat.getRowCount());
 
+        // create index
+        CreateIndexParam indexParam = CreateIndexParam.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withFieldName(field2Name)
+                .withIndexType(IndexType.BIN_FLAT)
+                .withMetricType(MetricType.HAMMING)
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingInterval(500L)
+                .withSyncWaitingTimeout(30L)
+                .build();
+
+        R<RpcStatus> createIndexR = client.createIndex(indexParam);
+        assertEquals(R.Status.Success.getCode(), createIndexR.getStatus().intValue());
+
         // load collection
         R<RpcStatus> loadR = client.loadCollection(LoadCollectionParam.newBuilder()
                 .withCollectionName(randomCollectionName)
@@ -655,6 +669,20 @@ class MilvusMultiClientDockerTest {
         GetCollStatResponseWrapper stat = new GetCollStatResponseWrapper(statR.getData());
         System.out.println("Collection row count: " + stat.getRowCount());
 
+        // create index
+        CreateIndexParam indexParam = CreateIndexParam.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withFieldName(field2Name)
+                .withIndexType(IndexType.FLAT)
+                .withMetricType(MetricType.IP)
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingInterval(500L)
+                .withSyncWaitingTimeout(30L)
+                .build();
+
+        R<RpcStatus> createIndexR = client.createIndex(indexParam);
+        assertEquals(R.Status.Success.getCode(), createIndexR.getStatus().intValue());
+
         // load collection
         R<RpcStatus> loadR = client.loadCollection(LoadCollectionParam.newBuilder()
                 .withCollectionName(randomCollectionName)

+ 6 - 6
src/test/java/io/milvus/client/MilvusServiceClientTest.java

@@ -1181,19 +1181,19 @@ class MilvusServiceClientTest {
         MilvusServiceClient client = startClient();
 
         // test return ok for sync mode loading
-        mockServerImpl.setGetIndexStateResponse(GetIndexStateResponse.newBuilder()
-                .setState(IndexState.InProgress)
+        mockServerImpl.setDescribeIndexResponse(DescribeIndexResponse.newBuilder()
+                .addIndexDescriptions(IndexDescription.newBuilder().setState(IndexState.InProgress).build())
                 .build());
 
         new Thread(() -> {
             try {
                 TimeUnit.SECONDS.sleep(1);
-                mockServerImpl.setGetIndexStateResponse(GetIndexStateResponse.newBuilder()
-                        .setState(IndexState.Finished)
+                mockServerImpl.setDescribeIndexResponse(DescribeIndexResponse.newBuilder()
+                        .addIndexDescriptions(IndexDescription.newBuilder().setState(IndexState.Finished).build())
                         .build());
             } catch (InterruptedException e) {
-                mockServerImpl.setGetIndexStateResponse(GetIndexStateResponse.newBuilder()
-                        .setState(IndexState.Finished)
+                mockServerImpl.setDescribeIndexResponse(DescribeIndexResponse.newBuilder()
+                        .addIndexDescriptions(IndexDescription.newBuilder().setState(IndexState.Finished).build())
                         .build());
             }
         }, "RefreshIndexState").start();

+ 3 - 3
tests/milvustest/src/test/java/com/zilliz/milvustest/index/CreateIndexTest.java

@@ -359,9 +359,9 @@ public class CreateIndexTest extends BaseTest {
                             .withSyncWaitingTimeout(30L)
                             .withSyncWaitingInterval(500L)
                             .build());
-    System.out.println("Create index" + rpcStatusR);
+    System.out.println("Create index " + rpcStatusR);
     Assert.assertEquals(rpcStatusR.getStatus().intValue(), 1);
-    Assert.assertTrue(rpcStatusR.getException().getMessage().contains("index already exists"));
+    Assert.assertTrue(rpcStatusR.getException().getMessage().contains("at most one distinct index is allowed per field"));
 
   }
 
@@ -432,7 +432,7 @@ public class CreateIndexTest extends BaseTest {
                             .build());
     System.out.println("Create index" + rpcStatusR);
     softAssert.assertEquals(rpcStatusR.getStatus().intValue(), 1);
-    softAssert.assertTrue(rpcStatusR.getException().getMessage().contains("index already exists"));
+    softAssert.assertTrue(rpcStatusR.getException().getMessage().contains("at most one distinct index is allowed per field"));
     milvusClient.dropCollection(
             DropCollectionParam.newBuilder().withCollectionName(stringPKCollection).build());
     softAssert.assertAll();

+ 1 - 1
tests/milvustest/src/test/java/com/zilliz/milvustest/index/DescribeIndexTest.java

@@ -123,7 +123,7 @@ public class DescribeIndexTest extends BaseTest {
                             .withCollectionName("NonexistentCollection")
                             .build());
     Assert.assertEquals(describeIndexResponseR.getStatus().intValue(), 1);
-    Assert.assertTrue(describeIndexResponseR.getException().getMessage().contains("not found"));
+    Assert.assertTrue(describeIndexResponseR.getException().getMessage().contains("can't find"));
   }
 
 }

+ 15 - 8
tests/milvustest/src/test/java/com/zilliz/milvustest/index/DropIndexTest.java

@@ -64,6 +64,15 @@ public class DropIndexTest extends BaseTest {
                 .build());
     Assert.assertEquals(rpcStatusR.getStatus().intValue(), 0);
     Assert.assertEquals(rpcStatusR.getData().getMsg(), "Success");
+
+    R<RpcStatus> rpcStatusR2 =
+            milvusClient.dropIndex(
+                    DropIndexParam.newBuilder()
+                            .withCollectionName(collection)
+                            .withIndexName(CommonData.defaultIndex)
+                            .build());
+    Assert.assertEquals(rpcStatusR2.getStatus().intValue(), 0);
+    Assert.assertEquals(rpcStatusR2.getData().getMsg(), "Success");
   }
 
   @Severity(SeverityLevel.MINOR)
@@ -71,8 +80,8 @@ public class DropIndexTest extends BaseTest {
   public void dropIndexWithoutIndexName() {
     R<RpcStatus> rpcStatusR =
         milvusClient.dropIndex(DropIndexParam.newBuilder().withCollectionName(collection).build());
-    Assert.assertEquals(rpcStatusR.getStatus().intValue(),25);
-    Assert.assertTrue(rpcStatusR.getException().getMessage().contains("Index doesn't exist"));
+    Assert.assertEquals(rpcStatusR.getStatus().intValue(),0);
+    Assert.assertEquals(rpcStatusR.getData().getMsg(), "Success");
   }
 
   @Severity(SeverityLevel.NORMAL)
@@ -84,8 +93,8 @@ public class DropIndexTest extends BaseTest {
                 .withCollectionName(collection)
                 .withIndexName("book_id")
                 .build());
-    Assert.assertEquals(rpcStatusR.getStatus().intValue(), 25);
-    Assert.assertTrue(rpcStatusR.getException().getMessage().contains( "Index doesn't exist"));
+    Assert.assertEquals(rpcStatusR.getStatus().intValue(), 0);
+    Assert.assertEquals(rpcStatusR.getData().getMsg(), "Success");
   }
 
   @Severity(SeverityLevel.NORMAL)
@@ -97,10 +106,8 @@ public class DropIndexTest extends BaseTest {
                 .withCollectionName(collection)
                 .withIndexName("nonexistent")
                 .build());
-    Assert.assertEquals(rpcStatusR.getStatus().intValue(), 25);
-    Assert.assertEquals(
-        rpcStatusR.getException().getMessage(),
-        "Index doesn't exist");
+    Assert.assertEquals(rpcStatusR.getStatus().intValue(), 0);
+    Assert.assertEquals(rpcStatusR.getData().getMsg(), "Success");
   }
 
   @Severity(SeverityLevel.MINOR)

+ 3 - 4
tests/milvustest/src/test/java/com/zilliz/milvustest/index/GetIndexStateTest.java

@@ -78,7 +78,7 @@ public class GetIndexStateTest extends BaseTest {
                 .withCollectionName("NonexistentCollection")
                 .withIndexName(CommonData.defaultIndex)
                 .build());
-    Assert.assertEquals(getIndexStateResponseR.getStatus().intValue(), 1);
+    Assert.assertEquals(getIndexStateResponseR.getStatus().intValue(), 0);
     Assert.assertTrue(getIndexStateResponseR.getException().getMessage().contains("not found"));
   }
 
@@ -92,9 +92,8 @@ public class GetIndexStateTest extends BaseTest {
                 .withCollectionName(newCollection)
                 .withIndexName(CommonData.defaultIndex)
                 .build());
-    Assert.assertEquals(getIndexStateResponseR.getStatus().intValue(), 1);
-    Assert.assertTrue(
-        getIndexStateResponseR.getException().getMessage().contains("index not found"));
+    Assert.assertEquals(getIndexStateResponseR.getStatus().intValue(), 0);
+    Assert.assertEquals(getIndexStateResponseR.getData().getState(), IndexState.Finished);
     milvusClient.dropCollection(
         DropCollectionParam.newBuilder().withCollectionName(newCollection).build());
   }

+ 232 - 0
tests/milvustest/src/test/java/com/zilliz/milvustest/index/IndexLoadTest.java

@@ -0,0 +1,232 @@
+package com.zilliz.milvustest.index;
+
+import com.zilliz.milvustest.common.BaseTest;
+import com.zilliz.milvustest.common.CommonData;
+import com.zilliz.milvustest.common.CommonFunction;
+import io.milvus.param.IndexType;
+import io.milvus.param.MetricType;
+import io.milvus.param.R;
+import io.milvus.param.RpcStatus;
+import io.milvus.param.collection.DropCollectionParam;
+import io.milvus.param.collection.LoadCollectionParam;
+import io.milvus.param.collection.ReleaseCollectionParam;
+import io.milvus.param.index.CreateIndexParam;
+import io.milvus.param.index.DropIndexParam;
+import io.qameta.allure.Issue;
+import io.qameta.allure.Severity;
+import io.qameta.allure.SeverityLevel;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static com.zilliz.milvustest.util.MathUtil.combine;
+
+public class IndexLoadTest extends BaseTest {
+    public String collection;
+    public String binaryCollection;
+
+    @BeforeClass(description = "create collection for test",alwaysRun = true)
+    public void createCollection() {
+        collection = CommonFunction.createNewCollection();
+        binaryCollection = CommonFunction.createBinaryCollection();
+    }
+
+    @AfterClass(description = "drop collection after test",alwaysRun = true)
+    public void dropCollection() {
+        milvusClient.dropCollection(
+                DropCollectionParam.newBuilder().withCollectionName(collection).build());
+        milvusClient.dropCollection(
+                DropCollectionParam.newBuilder().withCollectionName(binaryCollection).build());
+    }
+
+    @DataProvider(name = "IndexTypes")
+    public Object[][] provideIndexType() {
+        return new Object[][] {
+                {IndexType.FLAT},
+                {IndexType.IVF_FLAT},
+                {IndexType.IVF_SQ8},
+                {IndexType.IVF_PQ},
+                {IndexType.HNSW},
+                {IndexType.ANNOY},
+                {IndexType.RHNSW_FLAT},
+                {IndexType.RHNSW_PQ},
+                {IndexType.RHNSW_SQ}
+        };
+    }
+
+
+    @DataProvider(name = "BinaryIndexTypes")
+    public Object[][] provideBinaryIndexType() {
+        return new Object[][] {{IndexType.BIN_IVF_FLAT}, {IndexType.BIN_FLAT}};
+    }
+
+    @DataProvider(name = "MetricType")
+    public Object[][] providerMetricType() {
+        return new Object[][] {{MetricType.L2}, {MetricType.IP}};
+    }
+
+    @DataProvider(name = "BinaryMetricType")
+    public Object[][] providerBinaryMetricType() {
+        return new Object[][] {
+                {MetricType.HAMMING},
+                {MetricType.JACCARD},
+                {MetricType.SUBSTRUCTURE},
+                {MetricType.SUPERSTRUCTURE},
+                {MetricType.TANIMOTO}
+        };
+    }
+
+    @DataProvider(name = "FloatIndex")
+    public Object[][] providerIndexForFloatCollection() {
+        return combine(provideIndexType(), providerMetricType());
+    }
+
+    @DataProvider(name = "BinaryIndex")
+    public Object[][] providerIndexForBinaryCollection() {
+        return combine(provideBinaryIndexType(), providerBinaryMetricType());
+    }
+
+    @Severity(SeverityLevel.NORMAL)
+    @Test(description = "Test create/drop index when collection is loaded for float vector", dataProvider = "FloatIndex",groups = {"Smoke"})
+    public void createIndexAfterLoadFloatCollection(IndexType indexType, MetricType metricType) {
+        // 1. create index params
+        CreateIndexParam createIndexParams = CreateIndexParam.newBuilder()
+                .withCollectionName(collection)
+                .withFieldName(CommonData.defaultVectorField)
+                .withMetricType(metricType)
+                .withIndexType(indexType)
+                .withExtraParam(CommonFunction.provideExtraParam(indexType))
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingTimeout(30L)
+                .withSyncWaitingInterval(500L)
+                .build();
+        // 2. create index
+        R<RpcStatus> rpcStatusR = milvusClient.createIndex(createIndexParams);
+        System.out.println("Create index" + rpcStatusR);
+        Assert.assertEquals(rpcStatusR.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR.getData().getMsg(), "Success");
+
+        // 3. load collection
+        R<RpcStatus> rpcStatusR2 = milvusClient.loadCollection(
+                LoadCollectionParam.newBuilder()
+                .withCollectionName(collection)
+                .withSyncLoad(Boolean.TRUE)
+                .build());
+        System.out.println("Load collection " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR2.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR2.getData().getMsg(), "Success");
+
+        // 4. create index
+        R<RpcStatus> rpcStatusR3 = milvusClient.createIndex(createIndexParams);
+        System.out.println("Create index " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR3.getStatus().intValue(), 1);
+        Assert.assertTrue(rpcStatusR3.getMessage().contains("create index failed, collection is loaded, please release it first"));
+
+        // 5. drop index
+        R<RpcStatus> rpcStatusR4 = milvusClient.dropIndex(
+                        DropIndexParam.newBuilder()
+                                .withCollectionName(collection)
+                                .build());
+        System.out.println("Drop index " + rpcStatusR4);
+        Assert.assertEquals(rpcStatusR4.getStatus().intValue(), 1);
+        Assert.assertTrue(rpcStatusR4.getMessage().contains("index cannot be dropped, collection is loaded, please release it first"));
+
+        // 6. release collection
+        R<RpcStatus> rpcStatusR5 = milvusClient.releaseCollection(
+                ReleaseCollectionParam.newBuilder()
+                        .withCollectionName(collection)
+                        .build());
+        System.out.println("Release collection " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR5.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR5.getData().getMsg(), "Success");
+
+        // 7. create index
+        R<RpcStatus> rpcStatusR6 =
+                milvusClient.createIndex(createIndexParams);
+        System.out.println("Create index " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR6.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR6.getData().getMsg(), "Success");
+
+        // 8. drop index
+        R<RpcStatus> rpcStatusR7 = milvusClient.dropIndex(
+                DropIndexParam.newBuilder()
+                        .withCollectionName(collection)
+                        .build());
+        System.out.println("Drop index " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR7.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR7.getData().getMsg(), "Success");
+    }
+
+    @Severity(SeverityLevel.NORMAL)
+    @Test(description = "Test create/drop index when collection is loaded for binary vector", dataProvider = "BinaryIndex",groups = {"Smoke"})
+    public void createIndexAfterLoadBinaryCollection(IndexType indexType, MetricType metricType) {
+        // 1. create index params
+        CreateIndexParam createIndexParams = CreateIndexParam.newBuilder()
+                .withCollectionName(binaryCollection)
+                .withFieldName(CommonData.defaultVectorField)
+                .withMetricType(metricType)
+                .withIndexType(indexType)
+                .withExtraParam(CommonFunction.provideExtraParam(indexType))
+                .withSyncMode(Boolean.TRUE)
+                .withSyncWaitingTimeout(30L)
+                .withSyncWaitingInterval(500L)
+                .build();
+        // 2. create index
+        R<RpcStatus> rpcStatusR = milvusClient.createIndex(createIndexParams);
+        System.out.println("Create index" + rpcStatusR);
+        Assert.assertEquals(rpcStatusR.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR.getData().getMsg(), "Success");
+
+        // 3. load collection
+        R<RpcStatus> rpcStatusR2 = milvusClient.loadCollection(
+                LoadCollectionParam.newBuilder()
+                        .withCollectionName(binaryCollection)
+                        .withSyncLoad(Boolean.TRUE)
+                        .build());
+        System.out.println("Load collection " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR2.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR2.getData().getMsg(), "Success");
+
+        // 4. create index
+        R<RpcStatus> rpcStatusR3 = milvusClient.createIndex(createIndexParams);
+        System.out.println("Create index " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR3.getStatus().intValue(), 1);
+        Assert.assertTrue(rpcStatusR3.getMessage().contains("create index failed, collection is loaded, please release it first"));
+
+        // 5. drop index
+        R<RpcStatus> rpcStatusR4 = milvusClient.dropIndex(
+                DropIndexParam.newBuilder()
+                        .withCollectionName(binaryCollection)
+                        .build());
+        System.out.println("Drop index " + rpcStatusR4);
+        Assert.assertEquals(rpcStatusR4.getStatus().intValue(), 1);
+        Assert.assertTrue(rpcStatusR4.getMessage().contains("index cannot be dropped, collection is loaded, please release it first"));
+
+        // 6. release collection
+        R<RpcStatus> rpcStatusR5 = milvusClient.releaseCollection(
+                ReleaseCollectionParam.newBuilder()
+                        .withCollectionName(collection)
+                        .build());
+        System.out.println("Release collection " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR5.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR5.getData().getMsg(), "Success");
+
+        // 7. create index
+        R<RpcStatus> rpcStatusR6 =
+                milvusClient.createIndex(createIndexParams);
+        System.out.println("Create index " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR6.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR6.getData().getMsg(), "Success");
+
+        // 8. drop index
+        R<RpcStatus> rpcStatusR7 = milvusClient.dropIndex(
+                DropIndexParam.newBuilder()
+                        .withCollectionName(collection)
+                        .build());
+        System.out.println("Drop index " + rpcStatusR);
+        Assert.assertEquals(rpcStatusR7.getStatus().intValue(), 0);
+        Assert.assertEquals(rpcStatusR7.getData().getMsg(), "Success");
+    }
+}