Ver código fonte

Refine the code (#219)

Signed-off-by: yhmo <yihua.mo@zilliz.com>
groot 3 anos atrás
pai
commit
9338bf098b
53 arquivos alterados com 4373 adições e 1285 exclusões
  1. 43 0
      docker-compose.yml
  2. 0 307
      examples/main/io/milvus/DDLExample.java
  3. 0 145
      examples/main/io/milvus/DMLExample.java
  4. 445 0
      examples/main/io/milvus/GeneralExample.java
  5. 0 6
      examples/pom.xml
  6. 6 6
      pom.xml
  7. 251 347
      src/main/java/io/milvus/client/AbstractMilvusGrpcClient.java
  8. 38 36
      src/main/java/io/milvus/client/MilvusClient.java
  9. 11 9
      src/main/java/io/milvus/client/MilvusServiceClient.java
  10. 28 0
      src/main/java/io/milvus/exception/ClientNotConnectedException.java
  11. 37 0
      src/main/java/io/milvus/exception/MilvusException.java
  12. 3 26
      src/main/java/io/milvus/exception/ParamException.java
  13. 3 1
      src/main/java/io/milvus/param/ConnectParam.java
  14. 7 0
      src/main/java/io/milvus/param/Constant.java
  15. 36 8
      src/main/java/io/milvus/param/Control/GetMetricsRequestParam.java
  16. 32 6
      src/main/java/io/milvus/param/Control/GetPersistentSegmentInfoParam.java
  17. 32 6
      src/main/java/io/milvus/param/Control/GetQuerySegmentInfoParam.java
  18. 35 0
      src/main/java/io/milvus/param/IndexType.java
  19. 12 0
      src/main/java/io/milvus/param/ParamUtils.java
  20. 9 2
      src/main/java/io/milvus/param/R.java
  21. 53 0
      src/main/java/io/milvus/param/alias/AlterAliasParam.java
  22. 53 0
      src/main/java/io/milvus/param/alias/CreateAliasParam.java
  23. 40 0
      src/main/java/io/milvus/param/alias/DropAliasParam.java
  24. 23 5
      src/main/java/io/milvus/param/collection/CreateCollectionParam.java
  25. 13 6
      src/main/java/io/milvus/param/collection/DescribeCollectionParam.java
  26. 13 6
      src/main/java/io/milvus/param/collection/DropCollectionParam.java
  27. 26 12
      src/main/java/io/milvus/param/collection/FieldType.java
  28. 13 6
      src/main/java/io/milvus/param/collection/GetCollectionStatisticsParam.java
  29. 10 3
      src/main/java/io/milvus/param/collection/HasCollectionParam.java
  30. 13 6
      src/main/java/io/milvus/param/collection/LoadCollectionParam.java
  31. 13 6
      src/main/java/io/milvus/param/collection/ReleaseCollectionParam.java
  32. 21 14
      src/main/java/io/milvus/param/collection/ShowCollectionsParam.java
  33. 72 19
      src/main/java/io/milvus/param/dml/CalcDistanceParam.java
  34. 22 9
      src/main/java/io/milvus/param/dml/DeleteParam.java
  35. 118 53
      src/main/java/io/milvus/param/dml/InsertParam.java
  36. 14 15
      src/main/java/io/milvus/param/dml/QueryParam.java
  37. 73 44
      src/main/java/io/milvus/param/dml/SearchParam.java
  38. 49 12
      src/main/java/io/milvus/param/index/CreateIndexParam.java
  39. 16 8
      src/main/java/io/milvus/param/index/DescribeIndexParam.java
  40. 16 8
      src/main/java/io/milvus/param/index/DropIndexParam.java
  41. 12 29
      src/main/java/io/milvus/param/index/GetIndexBuildProgressParam.java
  42. 16 8
      src/main/java/io/milvus/param/index/GetIndexStateParam.java
  43. 16 8
      src/main/java/io/milvus/param/partition/CreatePartitionParam.java
  44. 16 8
      src/main/java/io/milvus/param/partition/DropPartitionParam.java
  45. 16 8
      src/main/java/io/milvus/param/partition/GetPartitionStatisticsParam.java
  46. 16 8
      src/main/java/io/milvus/param/partition/HasPartitionParam.java
  47. 23 8
      src/main/java/io/milvus/param/partition/LoadPartitionsParam.java
  48. 23 8
      src/main/java/io/milvus/param/partition/ReleasePartitionsParam.java
  49. 15 9
      src/main/java/io/milvus/param/partition/ShowPartitionsParam.java
  50. 242 0
      src/test/java/io/milvus/client/MilvusClientDockerTest.java
  51. 1829 39
      src/test/java/io/milvus/client/MilvusServiceClientTest.java
  52. 21 7
      src/test/java/io/milvus/server/MockMilvusServer.java
  53. 429 8
      src/test/java/io/milvus/server/MockMilvusServerImpl.java

+ 43 - 0
docker-compose.yml

@@ -0,0 +1,43 @@
+version: '3.5'
+
+services:
+  etcd:
+    container_name: milvus-test-etcd
+    image: quay.io/coreos/etcd:v3.5.0
+    volumes:
+      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
+    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
+
+  minio:
+    container_name: milvus-test-minio
+    image: minio/minio:RELEASE.2020-12-03T00-03-10Z
+    environment:
+      MINIO_ACCESS_KEY: minioadmin
+      MINIO_SECRET_KEY: minioadmin
+    volumes:
+      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
+    command: minio server /minio_data
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
+      interval: 30s
+      timeout: 20s
+      retries: 3
+
+  standalone:
+    container_name: milvus-test-standalone
+    image: milvusdb/milvus:v2.0.0-rc7-20211011-d567b21
+    command: ["milvus", "run", "standalone"]
+    environment:
+      ETCD_ENDPOINTS: etcd:2379
+      MINIO_ADDRESS: minio:9000
+    volumes:
+      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
+    ports:
+      - "19530:19530"
+    depends_on:
+      - "etcd"
+      - "minio"
+
+networks:
+  default:
+    name: test-milvus

+ 0 - 307
examples/main/io/milvus/DDLExample.java

@@ -1,307 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package io.milvus;
-
-import io.milvus.client.MilvusServiceClient;
-import io.milvus.grpc.DataType;
-import io.milvus.grpc.DescribeCollectionResponse;
-import io.milvus.grpc.DescribeIndexResponse;
-import io.milvus.grpc.GetCollectionStatisticsResponse;
-import io.milvus.grpc.GetIndexBuildProgressResponse;
-import io.milvus.grpc.GetIndexStateResponse;
-import io.milvus.grpc.GetPartitionStatisticsResponse;
-import io.milvus.grpc.ShowCollectionsResponse;
-import io.milvus.grpc.ShowPartitionsResponse;
-import io.milvus.grpc.ShowType;
-import io.milvus.param.ConnectParam;
-import io.milvus.param.R;
-import io.milvus.param.RpcStatus;
-import io.milvus.param.collection.CreateCollectionParam;
-import io.milvus.param.collection.DescribeCollectionParam;
-import io.milvus.param.collection.DropCollectionParam;
-import io.milvus.param.collection.FieldType;
-import io.milvus.param.collection.GetCollectionStatisticsParam;
-import io.milvus.param.collection.HasCollectionParam;
-import io.milvus.param.collection.LoadCollectionParam;
-import io.milvus.param.collection.ReleaseCollectionParam;
-import io.milvus.param.collection.ShowCollectionParam;
-import io.milvus.param.index.CreateIndexParam;
-import io.milvus.param.index.DescribeIndexParam;
-import io.milvus.param.index.DropIndexParam;
-import io.milvus.param.index.GetIndexBuildProgressParam;
-import io.milvus.param.index.GetIndexStateParam;
-import io.milvus.param.partition.CreatePartitionParam;
-import io.milvus.param.partition.DropPartitionParam;
-import io.milvus.param.partition.GetPartitionStatisticsParam;
-import io.milvus.param.partition.HasPartitionParam;
-import io.milvus.param.partition.LoadPartitionsParam;
-import io.milvus.param.partition.ReleasePartitionsParam;
-import io.milvus.param.partition.ShowPartitionParam;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Milvus ddl api example
- *
- * @author changzechuan
- */
-public class DDLExample {
-
-    public static MilvusServiceClient milvusClient;
-
-    static {
-        ConnectParam connectParam = ConnectParam.Builder.newBuilder()
-                .withHost("localhost")
-                .withPort(19530)
-                .build();
-        milvusClient = new MilvusServiceClient(connectParam);
-    }
-
-    @Test
-    public void createCollection() {
-        FieldType[] fieldTypes = new FieldType[2];
-        FieldType fieldType1 = FieldType.Builder.newBuilder()
-                .withName("userID")
-                .withDescription("userId")
-                .withDataType(DataType.Int64)
-                .withAutoID(true)
-                .withPrimaryKey(true).build();
-
-        Map<String, String> typeParamsMap = new HashMap<>();
-        typeParamsMap.put("dim", "512");
-        FieldType fieldType2 = FieldType.Builder.newBuilder()
-                .withName("vector1")
-                .withDescription("match Vector")
-                .withDataType(DataType.FloatVector)
-                .withTypeParams(typeParamsMap).build();
-        fieldTypes[0] = fieldType1;
-        fieldTypes[1] = fieldType2;
-
-        CreateCollectionParam createCollectionReq = CreateCollectionParam.Builder.newBuilder()
-                .withCollectionName("collection1")
-                .withDescription("first collection")
-                .withShardsNum(2)
-                .withFieldTypes(fieldTypes).build();
-        R<RpcStatus> createCollection = milvusClient.createCollection(createCollectionReq);
-
-        System.out.println(createCollection);
-    }
-
-    @Test
-    public void dropCollection() {
-        R<RpcStatus> dropCollection = milvusClient.dropCollection(DropCollectionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-        System.out.println(dropCollection);
-    }
-
-    @Test
-    public void hasCollection() {
-        R<Boolean> hasCollection = milvusClient.hasCollection(HasCollectionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-
-        System.out.println(hasCollection);
-    }
-
-    @Test
-    public void loadCollection() {
-        R<RpcStatus> loadCollection = milvusClient.loadCollection(LoadCollectionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-        System.out.println(loadCollection);
-    }
-
-    @Test
-    public void releaseCollection() {
-        R<RpcStatus> releaseCollection = milvusClient.releaseCollection(ReleaseCollectionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-        System.out.println(releaseCollection);
-    }
-
-    @Test
-    public void describeCollection() {
-        R<DescribeCollectionResponse> describeCollection = milvusClient.describeCollection(DescribeCollectionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-        System.out.println(describeCollection);
-    }
-
-    @Test
-    public void getCollectionStatistics() {
-        R<GetCollectionStatisticsResponse> getCollectionStatistics = milvusClient.getCollectionStatistics(GetCollectionStatisticsParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-        System.out.println(getCollectionStatistics);
-    }
-
-    @Test
-    public void showCollections() {
-        String[] collectionNames = new String[]{"collection1"};
-        R<ShowCollectionsResponse> showCollections = milvusClient.showCollections(ShowCollectionParam.Builder
-                .newBuilder()
-                .withCollectionNames(collectionNames)
-                .withShowType(ShowType.All)
-                .build());
-        System.out.println(showCollections);
-    }
-
-    @Test
-    public void createPartition() {
-        R<RpcStatus> createPartition = milvusClient.createPartition(CreatePartitionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withPartitionName("par1")
-                .build());
-
-        System.out.println(createPartition);
-    }
-
-    @Test
-    public void dropPartition() {
-        R<RpcStatus> dropPartition = milvusClient.dropPartition(DropPartitionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withPartitionName("par1")
-                .build());
-
-        System.out.println(dropPartition);
-    }
-
-    @Test
-    public void hasPartition() {
-        R<Boolean> hasPartition = milvusClient.hasPartition(HasPartitionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withPartitionName("par1")
-                .build());
-
-        System.out.println(hasPartition);
-    }
-
-    @Test
-    public void loadPartitions() {
-        String[] partitionNames = new String[]{"par1"};
-        R<RpcStatus> loadPartition = milvusClient.loadPartitions(LoadPartitionsParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withPartitionNames(partitionNames)
-                .build());
-
-        System.out.println(loadPartition);
-    }
-
-    @Test
-    public void releasePartitions() {
-        String[] releaseNames = new String[]{"par1"};
-        R<RpcStatus> releasePartition = milvusClient.releasePartitions(ReleasePartitionsParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withPartitionNames(releaseNames)
-                .build());
-
-        System.out.println(releasePartition);
-    }
-
-    @Test
-    public void getPartitionStatistics() {
-        R<GetPartitionStatisticsResponse> getPartitionStatistics = milvusClient.getPartitionStatistics(GetPartitionStatisticsParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withPartitionName("par1")
-                .build());
-
-        System.out.println(getPartitionStatistics);
-    }
-
-    @Test
-    public void showPartitions() {
-        R<ShowPartitionsResponse> showPartitionsResponse = milvusClient.showPartitions(ShowPartitionParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .build());
-        System.out.println(showPartitionsResponse);
-    }
-
-    @Test
-    public void createIndex() {
-        Map<String, String> extraParam = new HashMap<>();
-        extraParam.put("index_type", "IVF_FLAT");
-        extraParam.put("metric_type", "IP");
-        extraParam.put("params", "{\"nlist\":10}");
-        R<RpcStatus> createIndex = milvusClient.createIndex(CreateIndexParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withFieldName("vector1")
-                .withExtraParam(extraParam)
-                .build());
-        System.out.println(createIndex);
-    }
-
-    @Test
-    public void dropIndex() {
-        R<RpcStatus> dropIndex = milvusClient.dropIndex(DropIndexParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withFieldName("vector1")
-                .build());
-        System.out.println(dropIndex);
-    }
-
-    @Test
-    public void describeIndex() {
-        R<DescribeIndexResponse> describeIndex = milvusClient.describeIndex(DescribeIndexParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withFieldName("vector1")
-                .build());
-        System.out.println(describeIndex);
-    }
-
-    @Test
-    public void getIndexState() {
-        R<GetIndexStateResponse> getIndexState = milvusClient.getIndexState(GetIndexStateParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withFieldName("vector1")
-                .build());
-        System.out.println(getIndexState);
-    }
-
-    @Test
-    public void getIndexBuildProgress() {
-        R<GetIndexBuildProgressResponse> getIndexBuildProgress = milvusClient.getIndexBuildProgress(GetIndexBuildProgressParam.Builder
-                .newBuilder()
-                .withCollectionName("collection1")
-                .withFieldName("vector1")
-                .withIndexName("_default_idx")
-                .build());
-        System.out.println(getIndexBuildProgress);
-    }
-}

+ 0 - 145
examples/main/io/milvus/DMLExample.java

@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package io.milvus;
-
-import com.google.protobuf.ByteString;
-import io.milvus.client.MilvusServiceClient;
-import io.milvus.grpc.*;
-import io.milvus.param.*;
-import io.milvus.param.dml.*;
-import org.junit.Test;
-
-import java.nio.ByteBuffer;
-import java.util.*;
-
-public class DMLExample {
-
-    public static MilvusServiceClient milvusClient;
-
-    //vector1
-    List<Float> vector1 = Arrays.asList(101f, 103f, 107f, 108f);
-    // vector2
-    List<Float> vector2 = Arrays.asList(111f, 112f, 113f, 114f);
-
-    static {
-        ConnectParam connectParam = ConnectParam.Builder.newBuilder()
-                .withHost("localhost")
-                .withPort(19530)
-                .build();
-        milvusClient = new MilvusServiceClient(connectParam);
-    }
-
-    @Test
-    public void insert() {
-        // save two vectors : id=101,value=[101,103,107,108] ; id=102,value=[111,112,113,114]
-        // primary field's name is xp , vector field name is vector
-        // collection name is test
-
-        String collectionName = "test";
-        String partitionName = "pT";
-
-        List<String> fieldNames = Arrays.asList("xp", "vector");
-        List<DataType> dataTypes = Arrays.asList(DataType.Int64, DataType.FloatVector);
-
-        // primaryKey ids
-        List<Long> ids = Arrays.asList(101L, 102L);
-
-        // vectors' list
-        List<List<Float>> vectors = new ArrayList<>();
-
-        vectors.add(vector1);
-        vectors.add(vector2);
-
-        // fieldValues; for ids, <?> is Long; for vectors <?> is List<Float>
-        List<List<?>> result = new ArrayList<>();
-        result.add(ids);
-        result.add(vectors);
-
-        InsertParam insertParam = InsertParam.Builder
-                .newBuilder(collectionName)
-                .setFieldNum(fieldNames.size())
-                .setFieldNames(fieldNames)
-                .setPartitionName(partitionName)
-                .setDataTypes(dataTypes)
-                .setFieldValues(result)
-                .build();
-
-        R<MutationResult> insert = milvusClient.insert(insertParam);
-        System.out.println(insert.getData());
-
-        R<FlushResponse> flush = milvusClient.flush(collectionName);
-        System.out.println(flush.getData());
-    }
-
-    @Test
-    public void delete() {
-        String collectionName = "test";
-        String partitionName = "pT";
-        DeleteParam build = DeleteParam.Builder.newBuilder()
-                .setCollectionName(collectionName)
-                .setPartitionName(partitionName)
-                .build();
-        R<MutationResult> delete = milvusClient.delete(build);
-        System.out.println(delete.getData());
-    }
-
-    @Test
-    public void search() {
-        String collectionName = "test";
-        String fieldName = "vector";
-        List<String> outFields = Collections.singletonList("xp");
-
-        HashMap<String, String> params = new HashMap<String, String>() {{
-            put("params", "{\"nprobe\":10}");
-        }};
-        SearchParam searchParam = SearchParam.Builder.newBuilder()
-                .setCollectionName(collectionName)
-                .setMetricType(MetricType.L2)
-                .setOutFields(outFields)
-                .setTopK(5)
-                .setVectors(Collections.singletonList(vector1))
-                .setVectorFieldName(fieldName)
-                .setDslType(DslType.BoolExprV1)
-                .setDsl("xp > 100")
-                .setParams(params)
-                .build();
-
-
-        R<SearchResults> search = milvusClient.search(searchParam);
-        System.out.println(search);
-    }
-
-    @Test
-    public void calDistance() {
-        CalcDistanceParam calcDistanceParam = new CalcDistanceParam(vector1, vector2, MetricType.L2);
-        R<CalcDistanceResults> calcDistanceResultsR = milvusClient.calcDistance(calcDistanceParam);
-        System.out.println(calcDistanceResultsR);
-    }
-
-    @Test
-    public void query() {
-        String collectionName = "test";
-        QueryParam test = QueryParam.Builder.newBuilder("xp in [ 101, 102]")
-                .setCollectionName(collectionName)
-                .build();
-        R<QueryResults> query = milvusClient.query(test);
-        System.out.println(query);
-    }
-}

+ 445 - 0
examples/main/io/milvus/GeneralExample.java

@@ -0,0 +1,445 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.milvus;
+
+import io.milvus.client.MilvusServiceClient;
+import io.milvus.grpc.*;
+import io.milvus.param.*;
+import io.milvus.param.collection.*;
+import io.milvus.param.dml.*;
+import io.milvus.param.index.*;
+import io.milvus.param.partition.*;
+
+import java.util.*;
+import java.util.Random;
+
+public class GeneralExample {
+
+    public static MilvusServiceClient milvusClient;
+
+    static {
+        ConnectParam connectParam = ConnectParam.Builder.newBuilder()
+                .withHost("localhost")
+                .withPort(19530)
+                .build();
+        milvusClient = new MilvusServiceClient(connectParam);
+    }
+
+    public static final String COLLECTION_NAME = "TEST";
+    public static final String ID_FIELD = "userID";
+    public static final String VECTOR_FIELD = "userFace";
+    public static final Integer VECTOR_DIM = 64;
+
+    public static final IndexType INDEX_TYPE = IndexType.IVF_FLAT;
+    public static final String INDEX_PARAM = "{\"nlist\":128}";
+    public static final MetricType METRIC_TYPE = MetricType.IP;
+
+    public static final Integer SEARCH_K = 5;
+    public static final String SEARCH_PARAM = "{\"nprobe\":10}";
+
+    public R<RpcStatus> createCollection() {
+        System.out.println("========== createCollection() ==========");
+        FieldType[] fieldTypes = new FieldType[2];
+        FieldType fieldType1 = FieldType.Builder.newBuilder()
+                .withName(ID_FIELD)
+                .withDescription("user identification")
+                .withDataType(DataType.Int64)
+                .withAutoID(false)
+                .withPrimaryKey(true)
+                .build();
+
+        FieldType fieldType2 = FieldType.Builder.newBuilder()
+                .withName(VECTOR_FIELD)
+                .withDescription("face embedding")
+                .withDataType(DataType.FloatVector)
+                .withDimension(VECTOR_DIM)
+                .build();
+        fieldTypes[0] = fieldType1;
+        fieldTypes[1] = fieldType2;
+
+        CreateCollectionParam createCollectionReq = CreateCollectionParam.Builder.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withDescription("customer info")
+                .withShardsNum(2)
+                .withFieldTypes(fieldTypes)
+                .build();
+        R<RpcStatus> response = milvusClient.createCollection(createCollectionReq);
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> dropCollection() {
+        System.out.println("========== dropCollection() ==========");
+        R<RpcStatus> response = milvusClient.dropCollection(DropCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<Boolean> hasCollection() {
+        System.out.println("========== hasCollection() ==========");
+        R<Boolean> response = milvusClient.hasCollection(HasCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> loadCollection() {
+        System.out.println("========== loadCollection() ==========");
+        R<RpcStatus> response = milvusClient.loadCollection(LoadCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> releaseCollection() {
+        System.out.println("========== releaseCollection() ==========");
+        R<RpcStatus> response = milvusClient.releaseCollection(ReleaseCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<DescribeCollectionResponse> describeCollection() {
+        System.out.println("========== describeCollection() ==========");
+        R<DescribeCollectionResponse> response = milvusClient.describeCollection(DescribeCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<GetCollectionStatisticsResponse> getCollectionStatistics() {
+        System.out.println("========== getCollectionStatistics() ==========");
+        R<GetCollectionStatisticsResponse> response = milvusClient.getCollectionStatistics(GetCollectionStatisticsParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<ShowCollectionsResponse> showCollections() {
+        System.out.println("========== showCollections() ==========");
+        String[] collectionNames = new String[]{COLLECTION_NAME};
+        R<ShowCollectionsResponse> response = milvusClient.showCollections(ShowCollectionsParam.Builder
+                .newBuilder()
+                .withCollectionNames(collectionNames)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> createPartition(String partitionName) {
+        System.out.println("========== createPartition() ==========");
+        R<RpcStatus> response = milvusClient.createPartition(CreatePartitionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionName(partitionName)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> dropPartition(String partitionName) {
+        System.out.println("========== dropPartition() ==========");
+        R<RpcStatus> response = milvusClient.dropPartition(DropPartitionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionName(partitionName)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<Boolean> hasPartition(String partitionName) {
+        System.out.println("========== hasPartition() ==========");
+        R<Boolean> response = milvusClient.hasPartition(HasPartitionParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionName(partitionName)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> loadPartition(String partitionName) {
+        System.out.println("========== loadPartition() ==========");
+        String[] partitionNames = new String[]{partitionName};
+        R<RpcStatus> response = milvusClient.loadPartitions(LoadPartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionNames(partitionNames)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> releasePartition(String partitionName) {
+        System.out.println("========== releasePartition() ==========");
+        String[] releaseNames = new String[]{partitionName};
+        R<RpcStatus> response = milvusClient.releasePartitions(ReleasePartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionNames(releaseNames)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<GetPartitionStatisticsResponse> getPartitionStatistics(String partitionName) {
+        System.out.println("========== getPartitionStatistics() ==========");
+        R<GetPartitionStatisticsResponse> response = milvusClient.getPartitionStatistics(GetPartitionStatisticsParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionName(partitionName)
+                .build());
+
+        System.out.println(response);
+        return response;
+    }
+
+    public R<ShowPartitionsResponse> showPartitions() {
+        System.out.println("========== showPartitions() ==========");
+        R<ShowPartitionsResponse> response = milvusClient.showPartitions(ShowPartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> createIndex() {
+        System.out.println("========== createIndex() ==========");
+        R<RpcStatus> response = milvusClient.createIndex(CreateIndexParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldName(VECTOR_FIELD)
+                .withIndexType(INDEX_TYPE)
+                .withMetricType(METRIC_TYPE)
+                .withExtraParam(INDEX_PARAM)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<RpcStatus> dropIndex() {
+        System.out.println("========== dropIndex() ==========");
+        R<RpcStatus> response = milvusClient.dropIndex(DropIndexParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldName(VECTOR_FIELD)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<DescribeIndexResponse> describeIndex() {
+        System.out.println("========== describeIndex() ==========");
+        R<DescribeIndexResponse> response = milvusClient.describeIndex(DescribeIndexParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldName(VECTOR_FIELD)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<GetIndexStateResponse> getIndexState() {
+        System.out.println("========== getIndexState() ==========");
+        R<GetIndexStateResponse> response = milvusClient.getIndexState(GetIndexStateParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldName(VECTOR_FIELD)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<GetIndexBuildProgressResponse> getIndexBuildProgress() {
+        System.out.println("========== getIndexBuildProgress() ==========");
+        R<GetIndexBuildProgressResponse> response = milvusClient.getIndexBuildProgress(GetIndexBuildProgressParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+        System.out.println(response);
+        return response;
+    }
+
+    public R<MutationResult> insert(String partitionName, Long count) {
+        System.out.println("========== insert() ==========");
+        List<Long> ids = new ArrayList<>();
+        List<List<Float>> vectors = new ArrayList<>();
+
+        Random ran=new Random();
+        for (Long i = 0L; i < count; ++i) {
+            ids.add(i + 100L);
+            List<Float> vector = new ArrayList<>();
+            for (int d = 0; d < VECTOR_DIM; ++d) {
+                vector.add(ran.nextFloat());
+            }
+            vectors.add(vector);
+        }
+
+        List<InsertParam.Field> fields = new ArrayList<>();
+        fields.add(new InsertParam.Field(ID_FIELD, DataType.Int64, ids));
+        fields.add(new InsertParam.Field(VECTOR_FIELD, DataType.FloatVector, vectors));
+
+        InsertParam insertParam = InsertParam.Builder
+                .newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionName(partitionName)
+                .withFields(fields)
+                .build();
+
+        R<MutationResult> response = milvusClient.insert(insertParam);
+        System.out.println(response);
+
+        R<FlushResponse> ret = milvusClient.flush(COLLECTION_NAME);
+        System.out.println(ret.getData());
+
+        return response;
+    }
+
+    public R<MutationResult> delete(String partitionName, String expr) {
+        System.out.println("========== delete() ==========");
+        DeleteParam build = DeleteParam.Builder.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withPartitionName(partitionName)
+                .withExpr(expr)
+                .build();
+        R<MutationResult> response = milvusClient.delete(build);
+        System.out.println(response.getData());
+        return response;
+    }
+
+    public R<SearchResults> search(String expr) {
+        System.out.println("========== search() ==========");
+        List<String> outFields = Collections.singletonList(ID_FIELD);
+
+        Random ran=new Random();
+        List<Float> vector = new ArrayList<>();
+        for (int d = 0; d < VECTOR_DIM; ++d) {
+            vector.add(ran.nextFloat());
+        }
+
+        SearchParam searchParam = SearchParam.Builder.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withMetricType(MetricType.L2)
+                .withOutFields(outFields)
+                .withTopK(SEARCH_K)
+                .withVectors(Collections.singletonList(vector))
+                .withVectorFieldName(VECTOR_FIELD)
+                .withExpr(expr)
+                .withParams(SEARCH_PARAM)
+                .build();
+
+
+        R<SearchResults> response = milvusClient.search(searchParam);
+        System.out.println(response);
+        return response;
+    }
+
+    public R<CalcDistanceResults> calDistance() {
+        System.out.println("========== calDistance() ==========");
+        Random ran=new Random();
+        List<Float> vector1 = new ArrayList<>();
+        List<Float> vector2 = new ArrayList<>();
+        for (int d = 0; d < VECTOR_DIM; ++d) {
+            vector1.add(ran.nextFloat());
+            vector2.add(ran.nextFloat());
+        }
+
+        CalcDistanceParam calcDistanceParam = CalcDistanceParam.Builder.newBuilder()
+                .withVectorsLeft(Collections.singletonList(vector1))
+                .withVectorsRight(Collections.singletonList(vector2))
+                .withMetricType(MetricType.L2)
+                .build();
+        R<CalcDistanceResults> response = milvusClient.calcDistance(calcDistanceParam);
+        System.out.println(response);
+        return response;
+    }
+
+    public R<QueryResults> query(String expr) {
+        System.out.println("========== query() ==========");
+        List<String> fields = Arrays.asList(ID_FIELD, VECTOR_FIELD);
+        QueryParam test = QueryParam.Builder.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withExpr(expr)
+                .withOutFields(fields)
+                .build();
+        R<QueryResults> response = milvusClient.query(test);
+        System.out.println(response);
+        return response;
+    }
+
+    public static void main(String[] args) throws InterruptedException {
+        GeneralExample example = new GeneralExample();
+
+        example.dropCollection();
+        example.createCollection();
+        example.hasCollection();
+        example.describeCollection();
+        example.showCollections();
+        example.loadCollection();
+        example.getCollectionStatistics();
+
+        final String partitionName = "p1";
+        example.createPartition(partitionName);
+        example.hasPartition(partitionName);
+        example.showPartitions();
+        example.loadPartition(partitionName);
+        example.getPartitionStatistics(partitionName);
+
+        final Long row_count = 10000L;
+        example.insert(partitionName, row_count);
+        example.createIndex();
+        example.describeIndex();
+        example.getIndexBuildProgress();
+        example.getIndexState();
+
+        example.delete(partitionName, ID_FIELD + " in [105, 106, 107]");
+        example.query(ID_FIELD + " in [101, 102]");
+        example.search("");
+        example.calDistance();
+
+        example.releasePartition(partitionName);
+        example.releaseCollection();
+        example.dropPartition(partitionName);
+        example.dropIndex();
+        example.dropCollection();
+    }
+}

+ 0 - 6
examples/pom.xml

@@ -75,12 +75,6 @@
             <artifactId>slf4j-api</artifactId>
             <version>1.7.30</version>
         </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.13.2</version>
-            <scope>compile</scope>
-        </dependency>
     </dependencies>
 
 </project>

+ 6 - 6
pom.xml

@@ -148,15 +148,15 @@
             <version>2.12.1</version>
         </dependency>
         <dependency>
-            <groupId>org.testcontainers</groupId>
-            <artifactId>testcontainers</artifactId>
-            <version>1.14.3</version>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13</version>
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.testcontainers</groupId>
-            <artifactId>junit-jupiter</artifactId>
-            <version>1.14.3</version>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>5.7.0</version>
             <scope>test</scope>
         </dependency>
     </dependencies>

+ 251 - 347
src/main/java/io/milvus/client/AbstractMilvusGrpcClient.java

@@ -21,84 +21,30 @@ package io.milvus.client;
 
 import com.google.protobuf.ByteString;
 import io.grpc.StatusRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
+import io.milvus.exception.ClientNotConnectedException;
 import io.milvus.exception.ParamException;
 import io.milvus.grpc.*;
-import io.milvus.param.*;
-import io.milvus.param.dml.*;
-import io.milvus.grpc.BoolResponse;
-import io.milvus.grpc.CollectionSchema;
-import io.milvus.grpc.CreateCollectionRequest;
-import io.milvus.grpc.CreateIndexRequest;
-import io.milvus.grpc.CreatePartitionRequest;
-import io.milvus.grpc.DescribeCollectionRequest;
-import io.milvus.grpc.DescribeCollectionResponse;
-import io.milvus.grpc.DescribeIndexRequest;
-import io.milvus.grpc.DescribeIndexResponse;
-import io.milvus.grpc.DropCollectionRequest;
-import io.milvus.grpc.DropIndexRequest;
-import io.milvus.grpc.DropPartitionRequest;
-import io.milvus.grpc.ErrorCode;
-import io.milvus.grpc.FieldSchema;
-import io.milvus.grpc.GetCollectionStatisticsRequest;
-import io.milvus.grpc.GetCollectionStatisticsResponse;
-import io.milvus.grpc.GetIndexBuildProgressRequest;
-import io.milvus.grpc.GetIndexBuildProgressResponse;
-import io.milvus.grpc.GetIndexStateRequest;
-import io.milvus.grpc.GetIndexStateResponse;
-import io.milvus.grpc.GetPartitionStatisticsRequest;
-import io.milvus.grpc.GetPartitionStatisticsResponse;
-import io.milvus.grpc.HasCollectionRequest;
-import io.milvus.grpc.HasPartitionRequest;
-import io.milvus.grpc.KeyValuePair;
-import io.milvus.grpc.LoadCollectionRequest;
-import io.milvus.grpc.LoadPartitionsRequest;
-import io.milvus.grpc.MilvusServiceGrpc;
-import io.milvus.grpc.ReleaseCollectionRequest;
-import io.milvus.grpc.ReleasePartitionsRequest;
-import io.milvus.grpc.ShowCollectionsRequest;
-import io.milvus.grpc.ShowCollectionsResponse;
-import io.milvus.grpc.ShowPartitionsRequest;
-import io.milvus.grpc.ShowPartitionsResponse;
-import io.milvus.grpc.Status;
+import io.milvus.param.Constant;
+import io.milvus.param.ParamUtils;
 import io.milvus.param.R;
 import io.milvus.param.RpcStatus;
-import io.milvus.param.collection.CreateCollectionParam;
-import io.milvus.param.collection.DescribeCollectionParam;
-import io.milvus.param.collection.DropCollectionParam;
-import io.milvus.param.collection.FieldType;
-import io.milvus.param.collection.GetCollectionStatisticsParam;
-import io.milvus.param.collection.HasCollectionParam;
-import io.milvus.param.collection.LoadCollectionParam;
-import io.milvus.param.collection.ReleaseCollectionParam;
-import io.milvus.param.collection.ShowCollectionParam;
-import io.milvus.param.index.CreateIndexParam;
-import io.milvus.param.index.DescribeIndexParam;
-import io.milvus.param.index.DropIndexParam;
-import io.milvus.param.index.GetIndexBuildProgressParam;
-import io.milvus.param.index.GetIndexStateParam;
-import io.milvus.param.partition.CreatePartitionParam;
-import io.milvus.param.partition.DropPartitionParam;
-import io.milvus.param.partition.GetPartitionStatisticsParam;
-import io.milvus.param.partition.HasPartitionParam;
-import io.milvus.param.partition.LoadPartitionsParam;
-import io.milvus.param.partition.ReleasePartitionsParam;
-import io.milvus.param.partition.ShowPartitionParam;
+import io.milvus.param.alias.AlterAliasParam;
+import io.milvus.param.alias.CreateAliasParam;
+import io.milvus.param.alias.DropAliasParam;
+import io.milvus.param.collection.*;
+import io.milvus.param.dml.*;
+import io.milvus.param.index.*;
+import io.milvus.param.partition.*;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.util.stream.Collectors;
 
 public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
@@ -108,7 +54,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     protected abstract MilvusServiceGrpc.MilvusServiceFutureStub futureStub();
 
-    protected abstract boolean maybeAvailable();
+    protected abstract boolean clientIsReady();
 
     @Override
     public R<FlushResponse> flush(String collectionName, String dbName) {
@@ -127,11 +73,12 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<FlushResponse> flush(List<String> collectionNames, String dbName) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
         for (String collectionName : collectionNames) {
-            if (collectionName == null || StringUtils.isBlank(collectionName)) {
-                return R.failed(R.Status.ParamError,
-                        "Collection name cannot be empty");
-            }
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
         }
 
         MsgBase msgBase = MsgBase.newBuilder().setMsgType(MsgType.Flush).build();
@@ -142,6 +89,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         try {
             flush = blockingStub().flush(flushRequest);
         } catch (Exception e) {
+            logger.error("[milvus] flush rpc request error:{}", e.getMessage());
             return R.failed(e);
         }
         return R.success(flush);
@@ -149,6 +97,9 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<MutationResult> delete(DeleteParam deleteParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
 
         DeleteRequest deleteRequest = DeleteRequest.newBuilder()
                 .setBase(MsgBase.newBuilder().setMsgType(MsgType.Delete).build())
@@ -160,6 +111,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         try {
             delete = blockingStub().delete(deleteRequest);
         } catch (Exception e) {
+            logger.error("[milvus] delete rpc request error:{}", e.getMessage());
             return R.failed(e);
         }
         return R.success(delete);
@@ -167,51 +119,46 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<MutationResult> insert(InsertParam insertParam) {
-        //check params : two steps
-        // 1、check sdk incoming params
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
         String collectionName = insertParam.getCollectionName();
         String partitionName = insertParam.getPartitionName();
-        int fieldNum = insertParam.getFieldNum();
-        List<String> fieldNames = insertParam.getFieldNames();
-        List<DataType> dataTypes = insertParam.getDataTypes();
-        List<List<?>> fieldValues = insertParam.getFieldValues();
-        Integer filedNameSize = Optional.ofNullable(fieldNames).map(List::size).orElse(0);
-        Integer dTypeSize = Optional.ofNullable(dataTypes).map(List::size).orElse(0);
-        int fieldValueSize = Optional.ofNullable(fieldValues).map(List::size).orElse(0);
-        if (fieldNum != fieldValueSize || fieldNum != filedNameSize || fieldNum != dTypeSize) {
-            throw new ParamException("size is illegal");
-        }
-
-        //2、need to DDL request to get collection meta schema and check vector dim;
-        // whether the collection schema needs to be cached locally todo
-        assert fieldValues != null;
-        int numRow = fieldValues.get(0).size();
-
-        //3、gen insert request
+        List<InsertParam.Field> fields = insertParam.getFields();
+
+        //1. gen insert request
         MsgBase msgBase = MsgBase.newBuilder().setMsgType(MsgType.Insert).build();
         InsertRequest.Builder insertBuilder = InsertRequest.newBuilder()
                 .setCollectionName(collectionName)
                 .setPartitionName(partitionName)
                 .setBase(msgBase)
-                .setNumRows(numRow);
+                .setNumRows(insertParam.getRowCount());
 
-        // gen fieldData
-        for (int i = 0; i < fieldNum; i++) {
-            insertBuilder.addFieldsData(genFieldData(fieldNames.get(i), dataTypes.get(i), fieldValues.get(i)));
+        //2. gen fieldData
+        // TODO: check field type(use DescribeCollection get schema to compare)
+        for (InsertParam.Field field : fields) {
+            insertBuilder.addFieldsData(genFieldData(field.getName(), field.getType(), field.getValues()));
         }
 
+        //3. call insert
         InsertRequest insertRequest = insertBuilder.build();
         MutationResult insert = null;
         try {
             insert = blockingStub().insert(insertRequest);
         } catch (Exception e) {
-            R.failed(e);
+            logger.error("[milvus] insert rpc request error:{}", e.getMessage());
+            return R.failed(e);
         }
         return R.success(insert);
     }
 
     @Override
     public R<SearchResults> search(SearchParam searchParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
         SearchRequest.Builder builder = SearchRequest.newBuilder()
                 .setDbName(searchParam.getDbName())
                 .setCollectionName(searchParam.getCollectionName());
@@ -219,14 +166,28 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
             searchParam.getPartitionNames().forEach(builder::addPartitionNames);
         }
 
-        List<List<Float>> vectors = searchParam.getVectors();
+        // prepare target vectors
+        // TODO: check target vector dimension(use DescribeColection get schema to compare)
+        List<?> vectors = searchParam.getVectors();
         List<ByteString> byteStrings = vectors.stream().map(vector -> {
-            ByteBuffer allocate1 = ByteBuffer.allocate(16);
-            vector.forEach(allocate1::putFloat);
-            byte[] array = allocate1.array();
-            return ByteString.copyFrom(array);
-        }).collect(Collectors.toList());
+            if (vector instanceof ByteBuffer) {
+                return ByteString.copyFrom((ByteBuffer) vector);
+            }
+
+            if (vector instanceof List) {
+                List list = (List) vector;
+                if (list.get(0) instanceof Float) {
+                    ByteBuffer buf = ByteBuffer.allocate(Float.BYTES * list.size());
+                    list.forEach(v -> buf.putFloat((Float) v));
+
+                    byte[] array = buf.array();
+                    return ByteString.copyFrom(array);
+                }
+            }
 
+            logger.error("Search target vector type is illegal(Only allow List<Float> or ByteBuffer)");
+            return null;
+        }).collect(Collectors.toList());
 
         PlaceholderValue.Builder pldBuilder = PlaceholderValue.newBuilder()
                 .setTag(Constant.VECTOR_TAG)
@@ -239,6 +200,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
         builder.setPlaceholderGroup(placeholderGroup.toByteString());
 
+        // search parameters
         builder.addSearchParams(
                 KeyValuePair.newBuilder()
                         .setKey(Constant.VECTOR_FIELD)
@@ -252,15 +214,14 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                 .addSearchParams(
                         KeyValuePair.newBuilder()
                                 .setKey(Constant.METRIC_TYPE)
-                                .setValue(searchParam.getMetricType().name())
+                                .setValue(searchParam.getMetricType())
                                 .build());
 
-        if (!searchParam.getParams().isEmpty() && null != searchParam.getParams().get(Constant.PARAMS)
-                && !searchParam.getParams().get(Constant.PARAMS).isEmpty()) {
+        if (null != searchParam.getParams() && !searchParam.getParams().isEmpty()) {
             builder.addSearchParams(
                     KeyValuePair.newBuilder()
                             .setKey(Constant.PARAMS)
-                            .setValue(searchParam.getParams().get(Constant.PARAMS))
+                            .setValue(searchParam.getParams())
                             .build());
         }
 
@@ -268,9 +229,10 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
             searchParam.getOutFields().forEach(builder::addOutputFields);
         }
 
-        builder.setDslType(searchParam.getDslType());
-        if (searchParam.getDsl() == null || searchParam.getDsl().isEmpty()) {
-            builder.setDsl(searchParam.getDsl());
+        // always use expression since dsl is discarded
+        builder.setDslType(DslType.BoolExprV1);
+        if (searchParam.getExpr() != null && !searchParam.getExpr().isEmpty()) {
+            builder.setDsl(searchParam.getExpr());
         }
 
         SearchRequest searchRequest = builder.build();
@@ -287,6 +249,10 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<QueryResults> query(QueryParam queryParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
         QueryRequest queryRequest = QueryRequest.newBuilder()
                 .setDbName(queryParam.getDbName())
                 .setCollectionName(queryParam.getCollectionName())
@@ -299,7 +265,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         try {
             query = this.blockingStub().query(queryRequest);
         } catch (Exception e) {
-            e.printStackTrace();
+//            e.printStackTrace();
+            logger.error("[milvus] query rpc request error:{}", e.getMessage());
             return R.failed(e);
         }
         return R.success(query);
@@ -307,19 +274,30 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<CalcDistanceResults> calcDistance(CalcDistanceParam calcDistanceParam) {
-        List<Float> vector1 = calcDistanceParam.getVector1();
-        List<Float> vector2 = calcDistanceParam.getVector2();
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
+        List<List<Float>> vectors_left = calcDistanceParam.getVectorsLeft();
+        List<List<Float>> vectors_right = calcDistanceParam.getVectorsRight();
+
+        FloatArray.Builder left_float_array = FloatArray.newBuilder();
+        for (List<Float> vector : vectors_left) {
+            left_float_array.addAllData(vector);
+        }
+
+        FloatArray.Builder right_float_array = FloatArray.newBuilder();
+        for (List<Float> vector : vectors_right) {
+            right_float_array.addAllData(vector);
+        }
 
         CalcDistanceRequest calcDistanceRequest = CalcDistanceRequest.newBuilder()
                 .setOpLeft(
                         VectorsArray.newBuilder()
                                 .setDataArray(
                                         VectorField.newBuilder()
-                                                .setFloatVector(
-                                                        FloatArray.newBuilder()
-                                                                .addAllData(vector1)
-                                                                .build())
-                                                .setDim(vector1.size())
+                                                .setFloatVector(left_float_array.build())
+                                                .setDim(vectors_left.get(0).size())
                                                 .build()
                                 )
                                 .build()
@@ -328,11 +306,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                         VectorsArray.newBuilder()
                                 .setDataArray(
                                         VectorField.newBuilder()
-                                                .setFloatVector(
-                                                        FloatArray.newBuilder()
-                                                                .addAllData(vector2)
-                                                                .build())
-                                                .setDim(vector2.size())
+                                                .setFloatVector(right_float_array.build())
+                                                .setDim(vectors_right.get(0).size())
                                                 .build()
                                 )
                                 .build()
@@ -340,7 +315,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                 .addParams(
                         KeyValuePair.newBuilder()
                                 .setKey("metric")
-                                .setValue(calcDistanceParam.getMetricType().name())
+                                .setValue(calcDistanceParam.getMetricType())
                                 .build()
                 )
                 .build();
@@ -356,29 +331,41 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     private FieldData genFieldData(String fieldName, DataType dataType, List<?> objects) {
         if (objects == null) {
-            throw new ParamException("params is null");
+            throw new ParamException("Cannot generate FieldData from null object");
         }
         FieldData.Builder builder = FieldData.newBuilder();
         if (vectorDataType.contains(dataType)) {
             if (dataType == DataType.FloatVector) {
                 List<Float> floats = new ArrayList<>();
-                // 每个object是个list
+                // each object is List<Float>
                 for (Object object : objects) {
                     if (object instanceof List) {
                         List list = (List) object;
-                        list.forEach(o -> floats.add((Float) o));
+                        floats.addAll(list);
                     } else {
-                        throw new ParamException("param type unsuitable");
+                        throw new ParamException("The type of FloatVector must be List<Float>");
                     }
                 }
+
                 int dim = floats.size() / objects.size();
                 FloatArray floatArray = FloatArray.newBuilder().addAllData(floats).build();
                 VectorField vectorField = VectorField.newBuilder().setDim(dim).setFloatVector(floatArray).build();
                 return builder.setFieldName(fieldName).setType(DataType.FloatVector).setVectors(vectorField).build();
             } else if (dataType == DataType.BinaryVector) {
-                List<ByteBuffer> bytes = objects.stream().map(p -> (ByteBuffer) p).collect(Collectors.toList());
-                ByteString byteString = ByteString.copyFrom((ByteBuffer) bytes);
-                int dim = objects.size();
+                ByteString byteString = null;
+                int dim = 0;
+                // each object is ByteBuffer
+                for (Object object : objects) {
+                    ByteBuffer buf = (ByteBuffer) object;
+                    ByteString tempStr = ByteString.copyFrom((ByteBuffer) buf);
+                    if (byteString == null){
+                        byteString = tempStr;
+                        dim = buf.position() * 8;
+                    } else {
+                        byteString.concat(tempStr);
+                    }
+                }
+
                 VectorField vectorField = VectorField.newBuilder().setDim(dim).setBinaryVector(byteString).build();
                 return builder.setFieldName(fieldName).setType(DataType.BinaryVector).setVectors(vectorField).build();
             }
@@ -386,7 +373,7 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
             switch (dataType) {
                 case None:
                 case UNRECOGNIZED:
-                    throw new ParamException("not support this dataType:" + dataType);
+                    throw new ParamException("Cannot support this dataType:" + dataType);
                 case Int64:
                 case Int32:
                 case Int16:
@@ -432,13 +419,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<Boolean> hasCollection(HasCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name is empty or not
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Server is not available");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         HasCollectionRequest hasCollectionRequest = HasCollectionRequest.newBuilder()
@@ -467,17 +449,13 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> createCollection(CreateCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         // Check whether the parameters are correct or not
-        if (requestParam == null || StringUtils.isBlank(requestParam.getCollectionName())
-                || requestParam.getShardsNum() <= 0
-                || requestParam.getFieldTypes() == null
-                || requestParam.getFieldTypes().length == 0) {
-            return R.failed(R.Status.ParamError,
-                    "Collection name cannot be empty and at least one field. Shards number must greater than zero.");
+        if (requestParam == null) {
+            return R.failed(new ParamException("Request param can not be null"));
         }
 
         // Construct CollectionSchema Params
@@ -486,11 +464,6 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                 .setDescription(requestParam.getDescription());
 
         for (FieldType fieldType : requestParam.getFieldTypes()) {
-            if (fieldType == null) {
-                return R.failed(R.Status.ParamError,
-                        "Collection field cannot be null");
-            }
-
             FieldSchema.Builder fieldSchemaBuilder = FieldSchema.newBuilder()
                     .setFieldID(fieldType.getFieldID())
                     .setName(fieldType.getName())
@@ -505,12 +478,6 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
                 typeParamsList.forEach(fieldSchemaBuilder::addTypeParams);
             }
 
-            // assemble indexParams for CollectionSchema
-            List<KeyValuePair> indexParamsList = assembleKvPair(fieldType.getIndexParams());
-            if (CollectionUtils.isNotEmpty(indexParamsList)) {
-                indexParamsList.forEach(fieldSchemaBuilder::addIndexParams);
-            }
-
             collectionSchemaBuilder.addFields(fieldSchemaBuilder.build());
         }
 
@@ -526,26 +493,24 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
             response = blockingStub().createCollection(createCollectionRequest);
 
             if (response.getErrorCode() == ErrorCode.Success) {
-                logInfo("Created collection successfully!\n{}", requestParam.toString());
+                logInfo("Created collection " + requestParam.getCollectionName() + " successfully!\n{}",
+                        requestParam.toString());
                 return R.success(new RpcStatus(RpcStatus.SUCCESS_MSG));
             } else {
+                logInfo("Created collection " + requestParam.getCollectionName() + " failed!\n{}", response);
                 return R.failed(R.Status.valueOf(response.getErrorCode().getNumber()), response.getReason());
             }
         } catch (StatusRuntimeException e) {
-            logError("createCollection RPC failed:\n{}", e.getStatus().toString());
+            logError("createCollection " + requestParam.getCollectionName() + " RPC failed:\n{}",
+                    e.getStatus().toString());
             return R.failed(e);
         }
     }
 
     @Override
     public R<RpcStatus> dropCollection(DropCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name is empty or not
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Inllegal input");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         DropCollectionRequest dropCollectionRequest = DropCollectionRequest.newBuilder()
@@ -570,13 +535,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> loadCollection(LoadCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name is empty or not
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Inllegal input");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         LoadCollectionRequest loadCollectionRequest = LoadCollectionRequest.newBuilder()
@@ -601,13 +561,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> releaseCollection(ReleaseCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name is empty or not
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Inllegal input");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         ReleaseCollectionRequest releaseCollectionRequest = ReleaseCollectionRequest.newBuilder()
@@ -633,13 +588,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<DescribeCollectionResponse> describeCollection(DescribeCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name is empty or not
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Inllegal input");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         DescribeCollectionRequest describeCollectionRequest = DescribeCollectionRequest.newBuilder()
@@ -665,13 +615,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<GetCollectionStatisticsResponse> getCollectionStatistics(GetCollectionStatisticsParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name is empty or not
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Inllegal input");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         GetCollectionStatisticsRequest getCollectionStatisticsRequest = GetCollectionStatisticsRequest.newBuilder()
@@ -696,10 +641,11 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
     }
 
     @Override
-    public R<ShowCollectionsResponse> showCollections(ShowCollectionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
+    public R<ShowCollectionsResponse> showCollections(ShowCollectionsParam requestParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
+
         ShowCollectionsRequest.Builder showCollectionRequestBuilder = ShowCollectionsRequest.newBuilder();
 
         String[] collectionNames = requestParam.getCollectionNames();
@@ -732,13 +678,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> createPartition(CreatePartitionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name or partition name is empty or not
-        if (checkPartitionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or partition name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         CreatePartitionRequest createPartitionRequest = CreatePartitionRequest.newBuilder()
@@ -764,13 +705,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> dropPartition(DropPartitionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name or partition name is empty or not
-        if (checkPartitionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or partition name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         DropPartitionRequest dropPartitionRequest = DropPartitionRequest.newBuilder()
@@ -796,13 +732,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<Boolean> hasPartition(HasPartitionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name or partition name is empty or not
-        if (checkPartitionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or partition name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         HasPartitionRequest hasPartitionRequest = HasPartitionRequest.newBuilder()
@@ -834,16 +765,10 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> loadPartitions(LoadPartitionsParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
-        // check requestParam
-        if (requestParam == null || StringUtils.isEmpty(requestParam.getCollectionName())
-                || requestParam.getPartitionNames() == null
-                || requestParam.getPartitionNames().length == 0) {
-            return R.failed(R.Status.ParamError, "Collection name or partition name cannot be empty");
-        }
         LoadPartitionsRequest.Builder loadPartitionsRequestBuilder = LoadPartitionsRequest.newBuilder();
 
         String[] partitionNames = requestParam.getPartitionNames();
@@ -871,15 +796,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> releasePartitions(ReleasePartitionsParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check requestParam
-        if (requestParam == null || StringUtils.isEmpty(requestParam.getCollectionName())
-                || requestParam.getPartitionNames() == null
-                || requestParam.getPartitionNames().length == 0) {
-            return R.failed(R.Status.ParamError, "Collection name or partition name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         ReleasePartitionsRequest.Builder releasePartitionsRequestBuilder = ReleasePartitionsRequest.newBuilder();
@@ -909,13 +827,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<GetPartitionStatisticsResponse> getPartitionStatistics(GetPartitionStatisticsParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // check whether if collection name or partition name is empty or not
-        if (checkPartitionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or partition name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         GetPartitionStatisticsRequest getPartitionStatisticsRequest = GetPartitionStatisticsRequest.newBuilder()
@@ -941,13 +854,9 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
     }
 
     @Override
-    public R<ShowPartitionsResponse> showPartitions(ShowPartitionParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        if (checkCollectionParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name cannot be empty");
+    public R<ShowPartitionsResponse> showPartitions(ShowPartitionsParam requestParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         ShowPartitionsRequest showPartitionsRequest = ShowPartitionsRequest.newBuilder()
@@ -972,16 +881,89 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
     }
 
     @Override
-    public R<RpcStatus> createIndex(CreateIndexParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
+    public R<RpcStatus> createAlias(CreateAliasParam requestParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
-        // check whether if create index param is valid or not
-        if (requestParam == null || StringUtils.isEmpty(requestParam.getCollectionName())
-                || StringUtils.isEmpty(requestParam.getFieldName())
-                || MapUtils.isEmpty(requestParam.getExtraParam())) {
-            return R.failed(R.Status.ParamError, "Collection name or field name cannot be empty");
+        CreateAliasRequest createAliasRequest = CreateAliasRequest.newBuilder()
+                .setCollectionName(requestParam.getCollectionName())
+                .setAlias(requestParam.getAlias())
+                .build();
+
+        Status response;
+        try {
+            response = blockingStub().createAlias(createAliasRequest);
+
+            if (response.getErrorCode() == ErrorCode.Success) {
+                logInfo("Create alias successfully!\n{}", requestParam.toString());
+                return R.success(new RpcStatus(RpcStatus.SUCCESS_MSG));
+            } else {
+                return R.failed(R.Status.valueOf(response.getErrorCode().getNumber()), response.getReason());
+            }
+        } catch (StatusRuntimeException e) {
+            logError("createAlias RPC failed:\n{}", e.getStatus().toString());
+            return R.failed(e);
+        }
+    }
+
+    @Override
+    public R<RpcStatus> dropAlias(DropAliasParam requestParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
+        DropAliasRequest dropAliasRequest = DropAliasRequest.newBuilder()
+                .setAlias(requestParam.getAlias())
+                .build();
+
+        Status response;
+        try {
+            response = blockingStub().dropAlias(dropAliasRequest);
+
+            if (response.getErrorCode() == ErrorCode.Success) {
+                logInfo("Drop alias successfully!\n{}", requestParam.toString());
+                return R.success(new RpcStatus(RpcStatus.SUCCESS_MSG));
+            } else {
+                return R.failed(R.Status.valueOf(response.getErrorCode().getNumber()), response.getReason());
+            }
+        } catch (StatusRuntimeException e) {
+            logError("dropAlias RPC failed:\n{}", e.getStatus().toString());
+            return R.failed(e);
+        }
+    }
+
+    @Override
+    public R<RpcStatus> alterAlias(AlterAliasParam requestParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
+        }
+
+        AlterAliasRequest alterAliasRequest = AlterAliasRequest.newBuilder()
+                .setCollectionName(requestParam.getCollectionName())
+                .setAlias(requestParam.getAlias())
+                .build();
+
+        Status response;
+        try {
+            response = blockingStub().alterAlias(alterAliasRequest);
+
+            if (response.getErrorCode() == ErrorCode.Success) {
+                logInfo("Alter alias successfully!\n{}", requestParam.toString());
+                return R.success(new RpcStatus(RpcStatus.SUCCESS_MSG));
+            } else {
+                return R.failed(R.Status.valueOf(response.getErrorCode().getNumber()), response.getReason());
+            }
+        } catch (StatusRuntimeException e) {
+            logError("alterAlias RPC failed:\n{}", e.getStatus().toString());
+            return R.failed(e);
+        }
+    }
+
+    @Override
+    public R<RpcStatus> createIndex(CreateIndexParam requestParam) {
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         CreateIndexRequest.Builder createIndexRequestBuilder = CreateIndexRequest.newBuilder();
@@ -1012,12 +994,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<RpcStatus> dropIndex(DropIndexParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        if (checkIndexParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or field name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         DropIndexRequest dropIndexRequest = DropIndexRequest.newBuilder()
@@ -1043,12 +1021,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<DescribeIndexResponse> describeIndex(DescribeIndexParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        if (checkIndexParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or field name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         DescribeIndexRequest describeIndexRequest = DescribeIndexRequest.newBuilder()
@@ -1075,12 +1049,8 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<GetIndexStateResponse> getIndexState(GetIndexStateParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        if (checkIndexParam(requestParam)) {
-            return R.failed(R.Status.ParamError, "Collection name or field name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         GetIndexStateRequest getIndexStateRequest = GetIndexStateRequest.newBuilder()
@@ -1108,19 +1078,12 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     @Override
     public R<GetIndexBuildProgressResponse> getIndexBuildProgress(GetIndexBuildProgressParam requestParam) {
-        if (checkServerConnection()) {
-            return R.failed(R.Status.ConnectFailed, "Server is not available");
-        }
-
-        // indexName is required in this rpc
-        if (checkIndexParam(requestParam) || StringUtils.isEmpty(requestParam.getIndexName())) {
-            return R.failed(R.Status.ParamError, "Collection name, field name, index name cannot be empty");
+        if (!clientIsReady()) {
+            return R.failed(new ClientNotConnectedException("Client rpc channel is not ready"));
         }
 
         GetIndexBuildProgressRequest getIndexBuildProgressRequest = GetIndexBuildProgressRequest.newBuilder()
                 .setCollectionName(requestParam.getCollectionName())
-                .setFieldName(requestParam.getFieldName())
-                .setIndexName(requestParam.getIndexName())
                 .build();
 
         GetIndexBuildProgressResponse response;
@@ -1141,65 +1104,6 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
         }
     }
 
-    private <T> boolean checkCollectionParam(T requestParam) {
-        Class<?> clazz = requestParam.getClass();
-        try {
-            Field collectionNameField = clazz.getDeclaredField("collectionName");
-            collectionNameField.setAccessible(true);
-            String collectionName = (String) collectionNameField.get(requestParam);
-            // if collectionName is empty, return true, else return false
-            return StringUtils.isEmpty(collectionName);
-        } catch (Exception e) {
-            logError("checkCollectionParam failed:\n{}", e.getMessage());
-            return true;
-        }
-    }
-
-    private <T> boolean checkPartitionParam(T requestParam) {
-        Class<?> clazz = requestParam.getClass();
-        try {
-            Field collectionNameField = clazz.getDeclaredField("collectionName");
-            collectionNameField.setAccessible(true);
-            String collectionName = (String) collectionNameField.get(requestParam);
-
-            Field partitionNameField = clazz.getDeclaredField("partitionName");
-            partitionNameField.setAccessible(true);
-            String partitionName = (String) partitionNameField.get(requestParam);
-
-            // if collectionName or partitionName is empty, return true, else return false
-            return (StringUtils.isEmpty(collectionName) || StringUtils.isEmpty(partitionName));
-        } catch (Exception e) {
-            // if param check failed, return true
-            return true;
-        }
-    }
-
-    private <T> boolean checkIndexParam(T requestParam) {
-        Class<?> clazz = requestParam.getClass();
-        try {
-            Field collectionNameField = clazz.getDeclaredField("collectionName");
-            collectionNameField.setAccessible(true);
-            String collectionName = (String) collectionNameField.get(requestParam);
-
-            Field fieldNameField = clazz.getDeclaredField("fieldName");
-            fieldNameField.setAccessible(true);
-            String fieldName = (String) fieldNameField.get(requestParam);
-            // if collectionName or fieldName is empty, return true, else return false
-            return (StringUtils.isEmpty(collectionName) || StringUtils.isEmpty(fieldName));
-        } catch (Exception e) {
-            // if param check failed, return true
-            return true;
-        }
-    }
-
-    private boolean checkServerConnection() {
-        if (!maybeAvailable()) {
-            logWarning("You are not connected to Milvus server");
-            return true;
-        }
-        return false;
-    }
-
     private List<KeyValuePair> assembleKvPair(Map<String, String> sourceMap) {
         List<KeyValuePair> result = new ArrayList<>();
         if (MapUtils.isNotEmpty(sourceMap)) {

+ 38 - 36
src/main/java/io/milvus/client/MilvusClient.java

@@ -19,41 +19,19 @@
 
 package io.milvus.client;
 
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
 import io.milvus.grpc.*;
-import io.milvus.param.*;
-import io.milvus.grpc.DescribeCollectionResponse;
-import io.milvus.grpc.DescribeIndexResponse;
-import io.milvus.grpc.GetCollectionStatisticsResponse;
-import io.milvus.grpc.GetIndexBuildProgressResponse;
-import io.milvus.grpc.GetIndexStateResponse;
-import io.milvus.grpc.GetPartitionStatisticsResponse;
-import io.milvus.grpc.ShowCollectionsResponse;
-import io.milvus.grpc.ShowPartitionsResponse;
+import io.milvus.param.R;
 import io.milvus.param.RpcStatus;
-import io.milvus.param.collection.CreateCollectionParam;
-import io.milvus.param.collection.DescribeCollectionParam;
-import io.milvus.param.collection.DropCollectionParam;
-import io.milvus.param.collection.GetCollectionStatisticsParam;
-import io.milvus.param.collection.HasCollectionParam;
-import io.milvus.param.collection.LoadCollectionParam;
-import io.milvus.param.collection.ReleaseCollectionParam;
-import io.milvus.param.collection.ShowCollectionParam;
+import io.milvus.param.alias.AlterAliasParam;
+import io.milvus.param.alias.CreateAliasParam;
+import io.milvus.param.alias.DropAliasParam;
+import io.milvus.param.collection.*;
 import io.milvus.param.dml.*;
-import io.milvus.param.index.CreateIndexParam;
-import io.milvus.param.index.DescribeIndexParam;
-import io.milvus.param.index.DropIndexParam;
-import io.milvus.param.index.GetIndexBuildProgressParam;
-import io.milvus.param.index.GetIndexStateParam;
-import io.milvus.param.partition.CreatePartitionParam;
-import io.milvus.param.partition.DropPartitionParam;
-import io.milvus.param.partition.GetPartitionStatisticsParam;
-import io.milvus.param.partition.HasPartitionParam;
-import io.milvus.param.partition.LoadPartitionsParam;
-import io.milvus.param.partition.ReleasePartitionsParam;
-import io.milvus.param.partition.ShowPartitionParam;
+import io.milvus.param.index.*;
+import io.milvus.param.partition.*;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 /** The Milvus Client Interface */
 public interface MilvusClient {
@@ -142,10 +120,10 @@ public interface MilvusClient {
     /**
      * List all collections or get collection loading status.
      *
-     * @param requestParam {@link ShowCollectionParam}
+     * @param requestParam {@link ShowCollectionsParam}
      * @return {status:result code, data: ShowCollectionsResponse{status,collection_names,collection_ids,created_timestamps,created_utc_timestamps}}
      */
-    R<ShowCollectionsResponse> showCollections(ShowCollectionParam requestParam);
+    R<ShowCollectionsResponse> showCollections(ShowCollectionsParam requestParam);
 
     /**
      * Create a partition in a collection.
@@ -198,10 +176,34 @@ public interface MilvusClient {
     /**
      * Show all partitions in a collection.
      *
-     * @param requestParam {@link ShowPartitionParam}
+     * @param requestParam {@link ShowPartitionsParam}
      * @return {status:result code,data:ShowPartitionsResponse{partition_names,partitionIDs,created_timestamps,created_utc_timestamps}}
      */
-    R<ShowPartitionsResponse> showPartitions(ShowPartitionParam requestParam);
+    R<ShowPartitionsResponse> showPartitions(ShowPartitionsParam requestParam);
+
+    /**
+     * Create alias for a collection.
+     *
+     * @param requestParam {@link CreateAliasParam}
+     * @return {status:result code,data:RpcStatus{msg: result message}}
+     */
+    R<RpcStatus> createAlias(CreateAliasParam requestParam);
+
+    /**
+     * Drop an alias.
+     *
+     * @param requestParam {@link DropAliasParam}
+     * @return {status:result code,data:RpcStatus{msg: result message}}
+     */
+    R<RpcStatus> dropAlias(DropAliasParam requestParam);
+
+    /**
+     * Alter alias from a collection to another.
+     *
+     * @param requestParam {@link AlterAliasParam}
+     * @return {status:result code,data:RpcStatus{msg: result message}}
+     */
+    R<RpcStatus> alterAlias(AlterAliasParam requestParam);
 
     /**
      * Create an index on a vector field. Note that index building is an async progress.

+ 11 - 9
src/main/java/io/milvus/client/MilvusServiceClient.java

@@ -19,10 +19,13 @@
 
 package io.milvus.client;
 
+import io.grpc.ConnectivityState;
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
-import io.milvus.param.ConnectParam;
+import io.milvus.exception.ClientNotConnectedException;
 import io.milvus.grpc.MilvusServiceGrpc;
+import io.milvus.param.ConnectParam;
+import io.milvus.param.R;
 
 import java.util.concurrent.TimeUnit;
 
@@ -56,20 +59,19 @@ public class MilvusServiceClient extends AbstractMilvusGrpcClient {
     }
 
     @Override
-    protected boolean maybeAvailable() {
-        switch (channel.getState(false)) {
-            case IDLE:
-            case CONNECTING:
-            case READY:
-                return true;
-            default:
+    protected boolean clientIsReady() {
+        ConnectivityState state = channel.getState(false);
+        switch (state) {
+            case SHUTDOWN:
                 return false;
+            default:
+                return true;
         }
     }
 
     @Override
     public void close(long maxWaitSeconds) {
-
+        channel.shutdownNow();
     }
 }
 

+ 28 - 0
src/main/java/io/milvus/exception/ClientNotConnectedException.java

@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.milvus.exception;
+
+import io.milvus.param.R;
+
+public class ClientNotConnectedException extends MilvusException {
+    public ClientNotConnectedException(String msg) {
+        super(msg, R.Status.ClientNotConnected.getCode());
+    }
+}

+ 37 - 0
src/main/java/io/milvus/exception/MilvusException.java

@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.milvus.exception;
+
+public abstract class MilvusException extends RuntimeException {
+    protected Integer status;
+
+    public MilvusException(String msg, Integer status) {
+        super(msg);
+        this.status = status;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+}

+ 3 - 26
src/main/java/io/milvus/exception/ParamException.java

@@ -19,33 +19,10 @@
 
 package io.milvus.exception;
 
-public class ParamException extends RuntimeException {
-    private String msg;
-    private Integer status;
+import io.milvus.param.R;
 
+public class ParamException extends MilvusException {
     public ParamException(String msg) {
-        this.msg = msg;
-        this.status = -1;
-    }
-
-    public ParamException(String msg, Integer status) {
-        this.msg = msg;
-        this.status = status;
-    }
-
-    public String getMsg() {
-        return msg;
-    }
-
-    public void setMsg(String msg) {
-        this.msg = msg;
-    }
-
-    public Integer getStatus() {
-        return status;
-    }
-
-    public void setStatus(Integer status) {
-        this.status = status;
+        super(msg, R.Status.ParamError.getCode());
     }
 }

+ 3 - 1
src/main/java/io/milvus/param/ConnectParam.java

@@ -19,6 +19,8 @@
 
 package io.milvus.param;
 
+import io.milvus.exception.ParamException;
+
 import javax.annotation.Nonnull;
 import java.util.concurrent.TimeUnit;
 
@@ -145,7 +147,7 @@ public class ConnectParam {
             return this;
         }
 
-        public ConnectParam build() {
+        public ConnectParam build() throws ParamException {
             return new ConnectParam(this);
         }
     }

+ 7 - 0
src/main/java/io/milvus/param/Constant.java

@@ -19,11 +19,18 @@
 
 package io.milvus.param;
 
+import io.milvus.grpc.DataType;
+
+import java.util.HashSet;
+import java.util.Set;
+
 public class Constant {
     // default value for search key
     public static final String VECTOR_TAG = "$0";
     public static final String VECTOR_FIELD = "anns_field";
+    public static final String VECTOR_DIM = "dim";
     public static final String TOP_K = "topk";
+    public static final String INDEX_TYPE = "index_type";
     public static final String METRIC_TYPE = "metric_type";
     public static final String PARAMS = "params";
 }

+ 36 - 8
src/main/java/io/milvus/param/Control/GetMetricsRequestParam.java

@@ -1,5 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 package io.milvus.param.Control;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author:weilongzhao
  * @time:2021/9/4 23:15
@@ -7,12 +31,12 @@ package io.milvus.param.Control;
 public class GetMetricsRequestParam {
     private final String request;
 
-    public String getRequest() {
-        return request;
+    private GetMetricsRequestParam(@Nonnull Builder builder) {
+        this.request = builder.request;
     }
 
-    public GetMetricsRequestParam(GetMetricsRequestParam.Builder builder) {
-        this.request = builder.request;
+    public String getRequest() {
+        return request;
     }
 
     public static final class Builder {
@@ -21,16 +45,20 @@ public class GetMetricsRequestParam {
         private Builder() {
         }
 
-        public static GetMetricsRequestParam.Builder newBuilder() {
-            return new GetMetricsRequestParam.Builder();
+        public static Builder newBuilder() {
+            return new Builder();
         }
 
-        public GetMetricsRequestParam.Builder withCollectionName(String request) {
+        public Builder withCollectionName(@Nonnull String request) {
             this.request = request;
             return this;
         }
 
-        public GetMetricsRequestParam build() {
+        public GetMetricsRequestParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(request, "Request string");
+
+            // TODO: check the request string is json format
+
             return new GetMetricsRequestParam(this);
         }
     }

+ 32 - 6
src/main/java/io/milvus/param/Control/GetPersistentSegmentInfoParam.java

@@ -1,5 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 package io.milvus.param.Control;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author:weilongzhao
  * @time:2021/9/4 22:20
@@ -7,12 +31,12 @@ package io.milvus.param.Control;
 public class GetPersistentSegmentInfoParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private GetPersistentSegmentInfoParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public GetPersistentSegmentInfoParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -25,12 +49,14 @@ public class GetPersistentSegmentInfoParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public GetPersistentSegmentInfoParam build() {
+        public GetPersistentSegmentInfoParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new GetPersistentSegmentInfoParam(this);
         }
     }

+ 32 - 6
src/main/java/io/milvus/param/Control/GetQuerySegmentInfoParam.java

@@ -1,5 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 package io.milvus.param.Control;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author:weilongzhao
  * @time:2021/9/4 23:01
@@ -7,12 +31,12 @@ package io.milvus.param.Control;
 public class GetQuerySegmentInfoParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private GetQuerySegmentInfoParam(@Nonnull GetQuerySegmentInfoParam.Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public GetQuerySegmentInfoParam(GetQuerySegmentInfoParam.Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -25,12 +49,14 @@ public class GetQuerySegmentInfoParam {
             return new GetQuerySegmentInfoParam.Builder();
         }
 
-        public GetQuerySegmentInfoParam.Builder withCollectionName(String collectionName) {
+        public GetQuerySegmentInfoParam.Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public GetQuerySegmentInfoParam build() {
+        public GetQuerySegmentInfoParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new GetQuerySegmentInfoParam(this);
         }
     }

+ 35 - 0
src/main/java/io/milvus/param/IndexType.java

@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.milvus.param;
+
+public enum IndexType {
+    INVALID,
+    IVF_FLAT,
+    IVF_PQ,
+    IVF_SQ8,
+    HNSW,
+    RHNSW_FLAT,
+    RHNSW_PQ,
+    RHNSW_SQ,
+    ANNOY,
+    //Only supported for byte vectors
+    BIN_IVF_FLAT,
+    ;
+}

+ 12 - 0
src/main/java/io/milvus/param/ParamUtils.java

@@ -0,0 +1,12 @@
+package io.milvus.param;
+
+import io.milvus.exception.ParamException;
+import org.apache.commons.lang3.StringUtils;
+
+public class ParamUtils {
+    public static void CheckNullEmptyString(String target, String name) throws ParamException {
+        if (target == null || StringUtils.isBlank(target)) {
+            throw new ParamException(name + " cannot be null or empty");
+        }
+    }
+}

+ 9 - 2
src/main/java/io/milvus/param/R.java

@@ -19,7 +19,9 @@
 
 package io.milvus.param;
 
+import io.milvus.exception.MilvusException;
 import io.milvus.grpc.ErrorCode;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 
 import java.util.Arrays;
 import java.util.Optional;
@@ -57,7 +59,12 @@ public class R<T> {
 
     public static <T> R<T> failed(Exception exception) {
         R<T> r = new R<>();
-        r.setStatus(Status.Unknown.getCode());
+        if (exception instanceof MilvusException) {
+            MilvusException e = (MilvusException) exception;
+            r.setStatus(e.getStatus());
+        } else {
+            r.setStatus(Status.Unknown.getCode());
+        }
         r.setException(exception);
         return r;
     }
@@ -153,7 +160,7 @@ public class R<T> {
     public String toString() {
         if (exception != null) {
             return "R{" +
-                    "exception=" + exception.getMessage() +
+                    "exception=" + ExceptionUtils.getMessage(exception) +
                     ", status=" + status +
                     ", data=" + data +
                     '}';

+ 53 - 0
src/main/java/io/milvus/param/alias/AlterAliasParam.java

@@ -0,0 +1,53 @@
+package io.milvus.param.alias;
+
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
+public class AlterAliasParam {
+    private final String collectionName;
+    private final String alias;
+
+    private AlterAliasParam(@Nonnull AlterAliasParam.Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.alias = builder.alias;
+    }
+
+    public String getCollectionName() {
+        return collectionName;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public static final class Builder {
+        private String collectionName;
+        private String alias;
+
+        private Builder() {
+        }
+
+        public static Builder newBuilder() {
+            return new Builder();
+        }
+
+        public Builder withCollectionName(@Nonnull String collectionName) {
+            this.collectionName = collectionName;
+            return this;
+        }
+
+        public Builder withAlias(@Nonnull String alias) {
+            this.alias = alias;
+            return this;
+        }
+
+        public AlterAliasParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(alias, "Alias");
+
+            return new AlterAliasParam(this);
+        }
+    }
+}

+ 53 - 0
src/main/java/io/milvus/param/alias/CreateAliasParam.java

@@ -0,0 +1,53 @@
+package io.milvus.param.alias;
+
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
+public class CreateAliasParam {
+    private final String collectionName;
+    private final String alias;
+
+    private CreateAliasParam(@Nonnull CreateAliasParam.Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.alias = builder.alias;
+    }
+
+    public String getCollectionName() {
+        return collectionName;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public static final class Builder {
+        private String collectionName;
+        private String alias;
+
+        private Builder() {
+        }
+
+        public static Builder newBuilder() {
+            return new Builder();
+        }
+
+        public Builder withCollectionName(@Nonnull String collectionName) {
+            this.collectionName = collectionName;
+            return this;
+        }
+
+        public Builder withAlias(@Nonnull String alias) {
+            this.alias = alias;
+            return this;
+        }
+
+        public CreateAliasParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(alias, "Alias");
+
+            return new CreateAliasParam(this);
+        }
+    }
+}

+ 40 - 0
src/main/java/io/milvus/param/alias/DropAliasParam.java

@@ -0,0 +1,40 @@
+package io.milvus.param.alias;
+
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
+public class DropAliasParam {
+    private final String alias;
+
+    private DropAliasParam(@Nonnull Builder builder) {
+        this.alias = builder.alias;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public static final class Builder {
+        private String alias;
+
+        private Builder() {
+        }
+
+        public static Builder newBuilder() {
+            return new Builder();
+        }
+
+        public Builder withAlias(@Nonnull String alias) {
+            this.alias = alias;
+            return this;
+        }
+
+        public DropAliasParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(alias, "Alias");
+
+            return new DropAliasParam(this);
+        }
+    }
+}

+ 23 - 5
src/main/java/io/milvus/param/collection/CreateCollectionParam.java

@@ -19,6 +19,9 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
 import javax.annotation.Nonnull;
 import java.util.Arrays;
 
@@ -56,7 +59,6 @@ public class CreateCollectionParam {
         return fieldTypes;
     }
 
-
     public static final class Builder {
         private String collectionName;
         private int shardsNum = 2;
@@ -70,7 +72,7 @@ public class CreateCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
@@ -80,17 +82,33 @@ public class CreateCollectionParam {
             return this;
         }
 
-        public Builder withDescription(String description) {
+        public Builder withDescription(@Nonnull String description) {
             this.description = description;
             return this;
         }
 
-        public Builder withFieldTypes(FieldType[] fieldTypes) {
+        public Builder withFieldTypes(@Nonnull FieldType[] fieldTypes) {
             this.fieldTypes = fieldTypes;
             return this;
         }
 
-        public CreateCollectionParam build() {
+        public CreateCollectionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
+            if (shardsNum <= 0) {
+                throw new ParamException("ShardNum must be larger than 0");
+            }
+
+            if (fieldTypes == null || fieldTypes.length <= 0) {
+                throw new ParamException("Field numbers must be larger than 0");
+            }
+
+            for (FieldType fieldType : fieldTypes) {
+                if (fieldType == null) {
+                    throw new ParamException("Collection field cannot be null");
+                }
+            }
+
             return new CreateCollectionParam(this);
         }
     }

+ 13 - 6
src/main/java/io/milvus/param/collection/DescribeCollectionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create collection RPC operation
  *
@@ -27,12 +32,12 @@ package io.milvus.param.collection;
 public class DescribeCollectionParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private DescribeCollectionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public DescribeCollectionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -45,12 +50,14 @@ public class DescribeCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public DescribeCollectionParam build() {
+        public DescribeCollectionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new DescribeCollectionParam(this);
         }
     }

+ 13 - 6
src/main/java/io/milvus/param/collection/DropCollectionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create collection RPC operation
  *
@@ -27,12 +32,12 @@ package io.milvus.param.collection;
 public class DropCollectionParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private DropCollectionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public DropCollectionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -45,12 +50,14 @@ public class DropCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public DropCollectionParam build() {
+        public DropCollectionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new DropCollectionParam(this);
         }
     }

+ 26 - 12
src/main/java/io/milvus/param/collection/FieldType.java

@@ -19,9 +19,14 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
 import io.milvus.grpc.DataType;
+import io.milvus.param.Constant;
+import io.milvus.param.ParamUtils;
 
 import javax.annotation.Nonnull;
+import javax.xml.crypto.Data;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -36,7 +41,6 @@ public class FieldType {
     private final String description;
     private final DataType dataType;
     private final Map<String,String> typeParams;
-    private final Map<String,String> indexParams;
     private final boolean autoID;
 
     private FieldType(@Nonnull Builder builder){
@@ -46,7 +50,6 @@ public class FieldType {
         this.description = builder.description;
         this.dataType = builder.dataType;
         this.typeParams = builder.typeParams;
-        this.indexParams = builder.indexParams;
         this.autoID = builder.autoID;
     }
 
@@ -74,10 +77,6 @@ public class FieldType {
         return typeParams;
     }
 
-    public Map<String, String> getIndexParams() {
-        return indexParams;
-    }
-
     public boolean isAutoID() {
         return autoID;
     }
@@ -89,7 +88,6 @@ public class FieldType {
         private String description;
         private DataType dataType;
         private Map<String,String> typeParams;
-        private Map<String,String> indexParams;
         private boolean autoID;
 
         private Builder() {
@@ -104,7 +102,7 @@ public class FieldType {
             return this;
         }
 
-        public Builder withName(String name) {
+        public Builder withName(@Nonnull String name) {
             this.name = name;
             return this;
         }
@@ -114,7 +112,7 @@ public class FieldType {
             return this;
         }
 
-        public Builder withDescription(String description) {
+        public Builder withDescription(@Nonnull String description) {
             this.description = description;
             return this;
         }
@@ -129,8 +127,12 @@ public class FieldType {
             return this;
         }
 
-        public Builder withIndexParams(Map<String, String> indexParams) {
-            this.indexParams = indexParams;
+        // for vector field, for easy use
+        public Builder withDimension(Integer dimension) {
+            if (this.typeParams == null) {
+                this.typeParams = new HashMap<>();
+            }
+            this.typeParams.put(Constant.VECTOR_DIM, dimension.toString());
             return this;
         }
 
@@ -139,7 +141,19 @@ public class FieldType {
             return this;
         }
 
-        public FieldType build() {
+        public FieldType build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(name, "Field name");
+
+            if (dataType == null || dataType == DataType.None) {
+                throw new ParamException("Field data type is illegal");
+            }
+
+            if (dataType == DataType.FloatVector || dataType == DataType.BinaryVector) {
+                if (typeParams == null || !typeParams.containsKey(Constant.VECTOR_DIM)) {
+                    throw new ParamException("Vector field dimension must be larger than zero");
+                }
+            }
+
             return new FieldType(this);
         }
     }

+ 13 - 6
src/main/java/io/milvus/param/collection/GetCollectionStatisticsParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create collection RPC operation
  *
@@ -27,12 +32,12 @@ package io.milvus.param.collection;
 public class GetCollectionStatisticsParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private GetCollectionStatisticsParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public GetCollectionStatisticsParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -45,12 +50,14 @@ public class GetCollectionStatisticsParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public GetCollectionStatisticsParam build() {
+        public GetCollectionStatisticsParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new GetCollectionStatisticsParam(this);
         }
     }

+ 10 - 3
src/main/java/io/milvus/param/collection/HasCollectionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create collection RPC operation
  *
@@ -31,7 +36,7 @@ public class HasCollectionParam {
         return collectionName;
     }
 
-    public HasCollectionParam(Builder builder) {
+    private HasCollectionParam(@Nonnull Builder builder) {
         this.collectionName = builder.collectionName;
     }
 
@@ -45,12 +50,14 @@ public class HasCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public HasCollectionParam build() {
+        public HasCollectionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new HasCollectionParam(this);
         }
     }

+ 13 - 6
src/main/java/io/milvus/param/collection/LoadCollectionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create collection RPC operation
  *
@@ -27,12 +32,12 @@ package io.milvus.param.collection;
 public class LoadCollectionParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    public LoadCollectionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public LoadCollectionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -45,12 +50,14 @@ public class LoadCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public LoadCollectionParam build() {
+        public LoadCollectionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new LoadCollectionParam(this);
         }
     }

+ 13 - 6
src/main/java/io/milvus/param/collection/ReleaseCollectionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create collection RPC operation
  *
@@ -27,12 +32,12 @@ package io.milvus.param.collection;
 public class ReleaseCollectionParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private ReleaseCollectionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public ReleaseCollectionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -45,12 +50,14 @@ public class ReleaseCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public ReleaseCollectionParam build() {
+        public ReleaseCollectionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
             return new ReleaseCollectionParam(this);
         }
     }

+ 21 - 14
src/main/java/io/milvus/param/collection/ShowCollectionParam.java → src/main/java/io/milvus/param/collection/ShowCollectionsParam.java

@@ -19,7 +19,9 @@
 
 package io.milvus.param.collection;
 
+import io.milvus.exception.ParamException;
 import io.milvus.grpc.ShowType;
+import io.milvus.param.ParamUtils;
 
 import javax.annotation.Nonnull;
 
@@ -28,10 +30,15 @@ import javax.annotation.Nonnull;
  *
  * @author changzechuan
  */
-public class ShowCollectionParam {
+public class ShowCollectionsParam {
     private final String[] collectionNames;
     private final ShowType showType;
 
+    private ShowCollectionsParam(@Nonnull Builder builder) {
+        this.collectionNames = builder.collectionNames;
+        this.showType = builder.showType;
+    }
+
     public String[] getCollectionNames() {
         return collectionNames;
     }
@@ -40,14 +47,12 @@ public class ShowCollectionParam {
         return showType;
     }
 
-    public ShowCollectionParam(@Nonnull Builder builder) {
-        this.collectionNames = builder.collectionNames;
-        this.showType = builder.showType;
-    }
-
     public static final class Builder {
         private String[] collectionNames;
-        private ShowType showType;
+        // showType:
+        //   default showType = ShowType.All
+        //   if collectionNames is not empty, set showType = ShowType.InMemory
+        private ShowType showType = ShowType.All;
 
         private Builder() {
         }
@@ -56,18 +61,20 @@ public class ShowCollectionParam {
             return new Builder();
         }
 
-        public Builder withCollectionNames(String[] collectionNames) {
+        public Builder withCollectionNames(@Nonnull String[] collectionNames) {
             this.collectionNames = collectionNames;
             return this;
         }
 
-        public Builder withShowType(ShowType showType) {
-            this.showType = showType;
-            return this;
-        }
+        public ShowCollectionsParam build() throws ParamException {
+            if (collectionNames != null && collectionNames.length != 0) {
+                for (String collectionName : collectionNames) {
+                    ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+                }
+                this.showType = ShowType.InMemory;
+            }
 
-        public ShowCollectionParam build() {
-            return new ShowCollectionParam(this);
+            return new ShowCollectionsParam(this);
         }
     }
 }

+ 72 - 19
src/main/java/io/milvus/param/dml/CalcDistanceParam.java

@@ -20,40 +20,93 @@
 package io.milvus.param.dml;
 
 import io.milvus.exception.ParamException;
+import io.milvus.param.Constant;
 import io.milvus.param.MetricType;
 
 import javax.annotation.Nonnull;
 import java.util.List;
 
 /**
- * only support two vectors cal
+ * currently only support float vectors calculation
  */
 public class CalcDistanceParam {
-    private final List<Float> vector1;
-    private final List<Float> vector2;
-    private final MetricType metricType;
-
-    public CalcDistanceParam(@Nonnull List<Float> vector1,
-                             @Nonnull List<Float> vector2,
-                             @Nonnull MetricType metricType) {
-        if (vector1.size() != vector2.size()) {
-            throw new ParamException("size is not equal");
-        }
+    private final List<List<Float>> vectors_left;
+    private final List<List<Float>> vectors_right;
+    private final String metricType;
 
-        this.vector1 = vector1;
-        this.vector2 = vector2;
-        this.metricType = metricType;
+    private CalcDistanceParam(@Nonnull Builder builder) {
+        this.vectors_left = builder.vectors_left;
+        this.vectors_right = builder.vectors_right;
+        this.metricType = builder.metricType.name();
     }
 
-    public List<Float> getVector1() {
-        return vector1;
+    public List<List<Float>> getVectorsLeft() {
+        return vectors_left;
     }
 
-    public List<Float> getVector2() {
-        return vector2;
+    public List<List<Float>> getVectorsRight() {
+        return vectors_right;
     }
 
-    public MetricType getMetricType() {
+    public String getMetricType() {
         return metricType;
     }
+
+    public static class Builder {
+        private List<List<Float>> vectors_left;
+        private List<List<Float>> vectors_right;
+        private MetricType metricType;
+
+        private Builder() {
+        }
+
+        public static Builder newBuilder() {
+            return new Builder();
+        }
+
+        public Builder withVectorsLeft(@Nonnull List<List<Float>> vectors) {
+            this.vectors_left = vectors;
+            return this;
+        }
+
+        public Builder withVectorsRight(@Nonnull List<List<Float>> vectors) {
+            this.vectors_right = vectors;
+            return this;
+        }
+
+        public Builder withMetricType(MetricType metricType) {
+            this.metricType = metricType;
+            return this;
+        }
+
+        public CalcDistanceParam build() throws ParamException {
+            if (metricType == MetricType.INVALID) {
+                throw new ParamException("Metric type is illegal");
+            }
+
+            if (vectors_left == null || vectors_left.isEmpty()) {
+                throw new ParamException("Left vectors can not be empty");
+            }
+
+            int count = vectors_left.get(0).size();
+            for (List<Float> vector : vectors_left) {
+                if (vector.size() != count) {
+                    throw new ParamException("Left vector's dimension must be equal");
+                }
+            }
+
+            if (vectors_right == null || vectors_right.isEmpty()) {
+                throw new ParamException("Right vectors can not be empty");
+            }
+
+            count = vectors_right.get(0).size();
+            for (List<Float> vector : vectors_right) {
+                if (vector.size() != count) {
+                    throw new ParamException("Right vector's dimension must be equal");
+                }
+            }
+
+            return new CalcDistanceParam(this);
+        }
+    }
 }

+ 22 - 9
src/main/java/io/milvus/param/dml/DeleteParam.java

@@ -19,17 +19,22 @@
 
 package io.milvus.param.dml;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
 import javax.annotation.Nonnull;
 
 public class DeleteParam {
     private final String dbName;
     private final String collectionName;
     private final String partitionName;
+    private final String expr;
 
     private DeleteParam(@Nonnull Builder builder) {
         this.dbName = builder.dbName;
         this.collectionName = builder.collectionName;
         this.partitionName = builder.partitionName;
+        this.expr = builder.expr;
     }
 
     public String getDbName() {
@@ -44,10 +49,15 @@ public class DeleteParam {
         return partitionName;
     }
 
+    public String getExpr() {
+        return expr;
+    }
+
     public static class Builder {
-        private String dbName = "";
+        private String dbName = ""; // reserved
         private String collectionName;
-        private String partitionName;
+        private String partitionName = "";
+        private String expr;
 
         private Builder() {
         }
@@ -56,22 +66,25 @@ public class DeleteParam {
             return new Builder();
         }
 
-        public Builder setPartitionName(@Nonnull String partitionName) {
-            this.partitionName = partitionName;
+        public Builder withCollectionName(@Nonnull String collectionName) {
+            this.collectionName = collectionName;
             return this;
         }
 
-        public Builder setDbName(@Nonnull String dbName) {
-            this.dbName = dbName;
+        public Builder withPartitionName(@Nonnull String partitionName) {
+            this.partitionName = partitionName;
             return this;
         }
 
-        public Builder setCollectionName(@Nonnull String collectionName) {
-            this.collectionName = collectionName;
+        public Builder withExpr(@Nonnull String expr) {
+            this.expr = expr;
             return this;
         }
 
-        public DeleteParam build() {
+        public DeleteParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(expr, "Expression");
+
             return new DeleteParam(this);
         }
     }

+ 118 - 53
src/main/java/io/milvus/param/dml/InsertParam.java

@@ -19,36 +19,36 @@
 
 package io.milvus.param.dml;
 
+import io.milvus.exception.ParamException;
 import io.milvus.grpc.DataType;
+import io.milvus.param.ParamUtils;
 
 import javax.annotation.Nonnull;
+import java.nio.ByteBuffer;
 import java.util.List;
 
 /**
- * fieldNames,dataTypes, fieldValues' order must be consistent.
- * explain fieldValues:
- *     if dataType is scalar: ? is basic type, like Integer,Long...
- *     if dataType is FloatVector: ? is List<Float>
+ * InsertParam.Field.values:
+ * if dataType is scalar: values is List<Integer>, List<Long>...
+ * if dataType is FloatVector: values is List<List<Float>>
+ * if dataType is BinaryVector: values is List<ByteBuffer>
  */
 public class InsertParam {
+    private final List<Field> fields;
+
     private final String collectionName;
     private final String partitionName;
-    //for check collectionFields
-    private final int fieldNum;
-    // field's name
-    private final List<String> fieldNames;
-    // field's dataType
-    private final List<DataType> dataTypes;
-    // field's values
-    private final List<List<?>> fieldValues;
+    private final int row_count;
 
     private InsertParam(@Nonnull Builder builder) {
         this.collectionName = builder.collectionName;
         this.partitionName = builder.partitionName;
-        this.fieldNum = builder.fieldNum;
-        this.fieldNames = builder.fieldNames;
-        this.dataTypes = builder.dataTypes;
-        this.fieldValues = builder.fieldValues;
+        this.fields = builder.fields;
+        this.row_count = builder.row_count;
+    }
+
+    public List<Field> getFields() {
+        return fields;
     }
 
     public String getCollectionName() {
@@ -59,65 +59,130 @@ public class InsertParam {
         return partitionName;
     }
 
-    public int getFieldNum() {
-        return fieldNum;
-    }
-
-    public List<String> getFieldNames() {
-        return fieldNames;
-    }
-
-    public List<DataType> getDataTypes() {
-        return dataTypes;
-    }
-
-    public List<List<?>> getFieldValues() {
-        return fieldValues;
+    public int getRowCount() {
+        return row_count;
     }
 
     public static class Builder {
-        private final String collectionName;
+        private String collectionName;
         private String partitionName = "_default";
-        private int fieldNum;
-        private List<String> fieldNames;
-        private List<DataType> dataTypes;
-        private List<List<?>> fieldValues;
+        private List<InsertParam.Field> fields;
+        private int row_count;
 
-        private Builder(@Nonnull String collectionName) {
-            this.collectionName = collectionName;
+        private Builder() {
         }
 
-        public static Builder newBuilder(@Nonnull String collectionName) {
-            return new Builder(collectionName);
+        public static Builder newBuilder() {
+            return new Builder();
         }
 
-        public Builder setPartitionName(@Nonnull String partitionName) {
-            this.partitionName = partitionName;
+        public Builder withCollectionName(@Nonnull String collectionName) {
+            this.collectionName = collectionName;
             return this;
         }
 
-        public Builder setFieldNum(int fieldNum) {
-            this.fieldNum = fieldNum;
+        public Builder withPartitionName(@Nonnull String partitionName) {
+            this.partitionName = partitionName;
             return this;
         }
 
-        public Builder setFieldNames(@Nonnull List<String> fieldNames) {
-            this.fieldNames = fieldNames;
+        public Builder withFields(@Nonnull List<InsertParam.Field> fields) {
+            this.fields = fields;
             return this;
         }
 
-        public Builder setDataTypes(@Nonnull List<DataType> dataTypes) {
-            this.dataTypes = dataTypes;
-            return this;
+        public InsertParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
+            if (fields.isEmpty()) {
+                throw new ParamException("Fields cannot be empty");
+            }
+
+            for (InsertParam.Field field : fields) {
+                if (field == null) {
+                    throw new ParamException("Field cannot be null");
+                }
+
+                ParamUtils.CheckNullEmptyString(field.getName(), "Field name");
+
+                if (field.getValues() == null || field.getValues().isEmpty()) {
+                    throw new ParamException("Field value cannot be empty");
+                }
+            }
+
+            // check row count
+            int count = fields.get(0).getValues().size();
+            for (InsertParam.Field field : fields) {
+                if (field.getValues().size() != count) {
+                    throw new ParamException("Row count of fields must be equal");
+                }
+            }
+            this.row_count = count;
+
+            if (count == 0) {
+                throw new ParamException("Row count is zero");
+            }
+
+            // check value type and vector dimension
+            for (InsertParam.Field field : fields) {
+                List<?> values = field.getValues();
+                if (field.getType() == DataType.FloatVector) {
+                    if (!(values.get(0) instanceof List)) {
+                        throw new ParamException("Float vector field's value must be Lst<Float>");
+                    }
+                    List first = (List) values.get(0);
+                    if (!(first.get(0) instanceof Float)) {
+                        throw new ParamException("Float vector field's value must be Lst<Float>");
+                    }
+
+                    int dim = first.size();
+                    for (int i = 1; i < values.size(); ++i) {
+                        List temp = (List) values.get(i);
+                        if (dim != temp.size()) {
+                            throw new ParamException("Vector dimension must be equal");
+                        }
+                    }
+                } else if (field.getType() == DataType.BinaryVector) {
+                    if (!(values.get(0) instanceof ByteBuffer)) {
+                        throw new ParamException("Binary vector field's value must be ByteBuffer");
+                    }
+
+                    ByteBuffer first = (ByteBuffer) values.get(0);
+                    int dim = first.position();
+                    for (int i = 1; i < values.size(); ++i) {
+                        ByteBuffer temp = (ByteBuffer) values.get(i);
+                        if (dim != temp.position()) {
+                            throw new ParamException("Vector dimension must be equal");
+                        }
+                    }
+                }
+            }
+
+            return new InsertParam(this);
         }
+    }
 
-        public Builder setFieldValues(@Nonnull List<List<?>> fieldValues) {
-            this.fieldValues = fieldValues;
-            return this;
+    public static class Field {
+        private final String name;
+        private final DataType type;
+        private final List<?> values;
+
+        public Field(String name, DataType type, List<?> values) {
+            this.name = name;
+            this.type = type;
+            this.values = values;
         }
 
-        public InsertParam build() {
-            return new InsertParam(this);
+        public String getName() {
+            return name;
+        }
+
+        public DataType getType() {
+            return type;
+        }
+
+        public List<?> getValues() {
+            return values;
         }
     }
 }

+ 14 - 15
src/main/java/io/milvus/param/dml/QueryParam.java

@@ -20,6 +20,8 @@
 package io.milvus.param.dml;
 
 import com.google.common.collect.Lists;
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
 
 import javax.annotation.Nonnull;
 import java.util.ArrayList;
@@ -61,46 +63,43 @@ public class QueryParam {
     }
 
     public static class Builder {
-        private String dbName = "";
+        private String dbName = ""; // reserved
         private String collectionName;
         private List<String> partitionNames = Lists.newArrayList();
         private List<String> outFields = new ArrayList<>();
         private String expr;
 
-        private Builder(@Nonnull String expr) {
-            this.expr = expr;
+        private Builder() {
         }
 
-        public static Builder newBuilder(@Nonnull String expr) {
-            return new Builder(expr);
+        public static Builder newBuilder() {
+            return new Builder();
         }
 
-        public Builder setDbName(@Nonnull String dbName) {
-            this.dbName = dbName;
-            return this;
-        }
-
-        public Builder setCollectionName(@Nonnull String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder setPartitionNames(@Nonnull List<String> partitionNames) {
+        public Builder withPartitionNames(@Nonnull List<String> partitionNames) {
             this.partitionNames = partitionNames;
             return this;
         }
 
-        public Builder setOutFields(List<String> outFields) {
+        public Builder withOutFields(@Nonnull List<String> outFields) {
             this.outFields = outFields;
             return this;
         }
 
-        public Builder setExpr(String expr) {
+        public Builder withExpr(@Nonnull String expr) {
             this.expr = expr;
             return this;
         }
 
-        public QueryParam build() {
+        public QueryParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(expr, "Expression");
+
             return new QueryParam(this);
         }
     }

+ 73 - 44
src/main/java/io/milvus/param/dml/SearchParam.java

@@ -20,37 +20,42 @@
 package io.milvus.param.dml;
 
 import com.google.common.collect.Lists;
-import io.milvus.grpc.DslType;
+import io.milvus.exception.ParamException;
 import io.milvus.param.MetricType;
+import io.milvus.param.ParamUtils;
 
 import javax.annotation.Nonnull;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+/**
+ * SearchParam.vectors:
+ * if is FloatVector: vectors is List<List<Float>>
+ * if is BinaryVector: vectors is List<ByteBuffer>
+ */
 public class SearchParam {
     private final String dbName;
     private final String collectionName;
     private final List<String> partitionNames;
-    private final MetricType metricType;
+    private final String metricType;
     private final String vectorFieldName;
     private final Integer topK;
-    private final DslType dslType;
-    private final String dsl;
+    private final String expr;
     private final List<String> outFields;
-    private final List<List<Float>> vectors;
-    private final Map<String, String> params;
+    private final List<?> vectors;
+    private final String params;
 
     private SearchParam(@Nonnull Builder builder) {
         this.dbName = builder.dbName;
         this.collectionName = builder.collectionName;
         this.partitionNames = builder.partitionNames;
-        this.metricType = builder.metricType;
+        this.metricType = builder.metricType.name();
         this.vectorFieldName = builder.vectorFieldName;
         this.topK = builder.topK;
-        this.dslType = builder.dslType;
-        this.dsl = builder.dsl;
+        this.expr = builder.expr;
         this.outFields = builder.outFields;
         this.vectors = builder.vectors;
         this.params = builder.params;
@@ -68,7 +73,7 @@ public class SearchParam {
         return partitionNames;
     }
 
-    public MetricType getMetricType() {
+    public String getMetricType() {
         return metricType;
     }
 
@@ -80,38 +85,33 @@ public class SearchParam {
         return topK;
     }
 
-    public DslType getDslType() {
-        return dslType;
-    }
-
-    public String getDsl() {
-        return dsl;
+    public String getExpr() {
+        return expr;
     }
 
     public List<String> getOutFields() {
         return outFields;
     }
 
-    public List<List<Float>> getVectors() {
+    public List<?> getVectors() {
         return vectors;
     }
 
-    public Map<String, String> getParams() {
+    public String getParams() {
         return params;
     }
 
     public static class Builder {
-        private String dbName = "";
+        private String dbName = ""; // reserved
         private String collectionName;
         private List<String> partitionNames = Lists.newArrayList();
         private MetricType metricType = MetricType.L2;
         private String vectorFieldName;
         private Integer topK;
-        private DslType dslType = DslType.BoolExprV1;
-        private String dsl;
+        private String expr;
         private List<String> outFields = new ArrayList<>();
-        private List<List<Float>> vectors;
-        private Map<String, String> params = new HashMap<>();
+        private List<?> vectors;
+        private String params;
 
         private Builder() {
         }
@@ -120,63 +120,92 @@ public class SearchParam {
             return new Builder();
         }
 
-        public Builder setDbName(@Nonnull String dbName) {
-            this.dbName = dbName;
-            return this;
-        }
-
-        public Builder setCollectionName(@Nonnull String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder setPartitionNames(@Nonnull List<String> partitionNames) {
+        public Builder withPartitionNames(@Nonnull List<String> partitionNames) {
             this.partitionNames = partitionNames;
             return this;
         }
 
-        public Builder setMetricType(@Nonnull MetricType metricType) {
+        public Builder withMetricType(@Nonnull MetricType metricType) {
             this.metricType = metricType;
             return this;
         }
 
-        public Builder setVectorFieldName(@Nonnull String vectorFieldName) {
+        public Builder withVectorFieldName(@Nonnull String vectorFieldName) {
             this.vectorFieldName = vectorFieldName;
             return this;
         }
 
-        public Builder setTopK(@Nonnull Integer topK) {
+        public Builder withTopK(@Nonnull Integer topK) {
             this.topK = topK;
             return this;
         }
 
-        public Builder setDslType(@Nonnull DslType dslType) {
-            this.dslType = dslType;
+        public Builder withExpr(@Nonnull String expr) {
+            this.expr = expr;
             return this;
         }
 
-        public Builder setDsl(@Nonnull String dsl) {
-            this.dsl = dsl;
-            return this;
-        }
-
-        public Builder setOutFields(@Nonnull List<String> outFields) {
+        public Builder withOutFields(@Nonnull List<String> outFields) {
             this.outFields = outFields;
             return this;
         }
 
-        public Builder setVectors(@Nonnull List<List<Float>> vectors) {
+        public Builder withVectors(@Nonnull List<?> vectors) {
             this.vectors = vectors;
             return this;
         }
 
 
-        public Builder setParams(@Nonnull Map<String, String> params) {
+        public Builder withParams(@Nonnull String params) {
             this.params = params;
             return this;
         }
 
-        public SearchParam build() {
+        public SearchParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(vectorFieldName, "Target field name");
+
+            if (metricType == MetricType.INVALID) {
+                throw new ParamException("Metric type is illegal");
+            }
+
+            if (vectors == null || vectors.isEmpty()) {
+                throw new ParamException("Target vectors can not be empty");
+            }
+
+            if (vectors.get(0) instanceof List) {
+                // float vectors
+                List first = (List) vectors.get(0);
+                if (!(first.get(0) instanceof Float)) {
+                    throw new ParamException("Float vector field's value must be Lst<Float>");
+                }
+
+                int dim = first.size();
+                for (int i = 1; i < vectors.size(); ++i) {
+                    List temp = (List) vectors.get(i);
+                    if (dim != temp.size()) {
+                        throw new ParamException("Target vector dimension must be equal");
+                    }
+                }
+            } else if (vectors.get(0) instanceof ByteBuffer) {
+                // binary vectors
+                ByteBuffer first = (ByteBuffer) vectors.get(0);
+                int dim = first.position();
+                for (int i = 1; i < vectors.size(); ++i) {
+                    ByteBuffer temp = (ByteBuffer) vectors.get(i);
+                    if (dim != temp.position()) {
+                        throw new ParamException("Target vector dimension must be equal");
+                    }
+                }
+            } else {
+                throw new ParamException("Target vector type must be Lst<Float> or ByteBuffer");
+            }
+
             return new SearchParam(this);
         }
     }

+ 49 - 12
src/main/java/io/milvus/param/index/CreateIndexParam.java

@@ -19,6 +19,16 @@
 
 package io.milvus.param.index;
 
+import com.google.api.Context;
+import com.google.api.Metric;
+import io.milvus.exception.ParamException;
+import io.milvus.param.Constant;
+import io.milvus.param.IndexType;
+import io.milvus.param.MetricType;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -27,7 +37,15 @@ import java.util.Map;
 public class CreateIndexParam {
     private final String collectionName;
     private final String fieldName;
-    private final Map<String, String> extraParam;
+    private final Map<String, String> extraParam = new HashMap<>();
+
+    private CreateIndexParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.fieldName = builder.fieldName;
+        this.extraParam.put(Constant.INDEX_TYPE, builder.indexType.name());
+        this.extraParam.put(Constant.METRIC_TYPE, builder.metricType.name());
+        this.extraParam.put(Constant.PARAMS, builder.extraParam);
+    }
 
     public String getCollectionName() {
         return collectionName;
@@ -41,16 +59,12 @@ public class CreateIndexParam {
         return extraParam;
     }
 
-    public CreateIndexParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.fieldName = builder.fieldName;
-        this.extraParam = builder.extraParam;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String fieldName;
-        private Map<String, String> extraParam;
+        private IndexType indexType;
+        private MetricType metricType;
+        private String extraParam;
 
         private Builder() {
         }
@@ -59,22 +73,45 @@ public class CreateIndexParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withFieldName(String fieldName) {
+        public Builder withFieldName(@Nonnull String fieldName) {
             this.fieldName = fieldName;
             return this;
         }
 
-        public Builder withExtraParam(Map<String, String> extraParam) {
+        public Builder withIndexType(@Nonnull IndexType indexType) {
+            this.indexType = indexType;
+            return this;
+        }
+
+        public Builder withMetricType(@Nonnull MetricType metricType) {
+            this.metricType = metricType;
+            return this;
+        }
+
+        public Builder withExtraParam(@Nonnull String extraParam) {
             this.extraParam = extraParam;
             return this;
         }
 
-        public CreateIndexParam build() {
+        public CreateIndexParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(fieldName, "Field name");
+
+            if (indexType == IndexType.INVALID) {
+                throw new ParamException("Index type is required");
+            }
+
+            if (metricType == MetricType.INVALID) {
+                throw new ParamException("Metric type is required");
+            }
+
+            ParamUtils.CheckNullEmptyString(extraParam, "Index extra param");
+
             return new CreateIndexParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/index/DescribeIndexParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.index;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author changzechuan
  */
@@ -26,6 +31,11 @@ public class DescribeIndexParam {
     private final String collectionName;
     private final String fieldName;
 
+    private DescribeIndexParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.fieldName = builder.fieldName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -34,11 +44,6 @@ public class DescribeIndexParam {
         return fieldName;
     }
 
-    public DescribeIndexParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.fieldName = builder.fieldName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String fieldName;
@@ -50,17 +55,20 @@ public class DescribeIndexParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withFieldName(String fieldName) {
+        public Builder withFieldName(@Nonnull String fieldName) {
             this.fieldName = fieldName;
             return this;
         }
 
-        public DescribeIndexParam build() {
+        public DescribeIndexParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(fieldName, "Field name");
+
             return new DescribeIndexParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/index/DropIndexParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.index;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author changzechuan
  */
@@ -26,6 +31,11 @@ public class DropIndexParam {
     private final String collectionName;
     private final String fieldName;
 
+    private DropIndexParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.fieldName = builder.fieldName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -34,11 +44,6 @@ public class DropIndexParam {
         return fieldName;
     }
 
-    public DropIndexParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.fieldName = builder.fieldName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String fieldName;
@@ -50,17 +55,20 @@ public class DropIndexParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withFieldName(String fieldName) {
+        public Builder withFieldName(@Nonnull String fieldName) {
             this.fieldName = fieldName;
             return this;
         }
 
-        public DropIndexParam build() {
+        public DropIndexParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(fieldName, "Field name");
+
             return new DropIndexParam(this);
         }
     }

+ 12 - 29
src/main/java/io/milvus/param/index/GetIndexBuildProgressParam.java

@@ -19,36 +19,27 @@
 
 package io.milvus.param.index;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author changzechuan
  */
 public class GetIndexBuildProgressParam {
     private final String collectionName;
-    private final String fieldName;
-    private final String indexName;
 
-    public String getCollectionName() {
-        return collectionName;
-    }
-
-    public String getFieldName() {
-        return fieldName;
-    }
-
-    public String getIndexName() {
-        return indexName;
+    private GetIndexBuildProgressParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-    public GetIndexBuildProgressParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.fieldName = builder.fieldName;
-        this.indexName = builder.indexName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
         private String collectionName;
-        private String fieldName;
-        private String indexName;
 
         private Builder() {
         }
@@ -57,22 +48,14 @@ public class GetIndexBuildProgressParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withFieldName(String fieldName) {
-            this.fieldName = fieldName;
-            return this;
-        }
-
-        public Builder withIndexName(String indexName) {
-            this.indexName = indexName;
-            return this;
-        }
+        public GetIndexBuildProgressParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
 
-        public GetIndexBuildProgressParam build() {
             return new GetIndexBuildProgressParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/index/GetIndexStateParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.index;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * @author changzechuan
  */
@@ -26,6 +31,11 @@ public class GetIndexStateParam {
     private final String collectionName;
     private final String fieldName;
 
+    private GetIndexStateParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.fieldName = builder.fieldName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -34,11 +44,6 @@ public class GetIndexStateParam {
         return fieldName;
     }
 
-    public GetIndexStateParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.fieldName = builder.fieldName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String fieldName;
@@ -50,17 +55,20 @@ public class GetIndexStateParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withFieldName(String fieldName) {
+        public Builder withFieldName(@Nonnull String fieldName) {
             this.fieldName = fieldName;
             return this;
         }
 
-        public GetIndexStateParam build() {
+        public GetIndexStateParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(fieldName, "Field name");
+
             return new GetIndexStateParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/partition/CreatePartitionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for create partition RPC operation
  *
@@ -28,6 +33,11 @@ public class CreatePartitionParam {
     private final String collectionName;
     private final String partitionName;
 
+    private CreatePartitionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionName = builder.partitionName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -36,11 +46,6 @@ public class CreatePartitionParam {
         return partitionName;
     }
 
-    public CreatePartitionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.partitionName = builder.partitionName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String partitionName;
@@ -52,17 +57,20 @@ public class CreatePartitionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withPartitionName(String partitionName) {
+        public Builder withPartitionName(@Nonnull String partitionName) {
             this.partitionName = partitionName;
             return this;
         }
 
-        public CreatePartitionParam build() {
+        public CreatePartitionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(partitionName, "Partition name");
+
             return new CreatePartitionParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/partition/DropPartitionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for drop partition RPC operation
  *
@@ -28,6 +33,11 @@ public class DropPartitionParam {
     private final String collectionName;
     private final String partitionName;
 
+    private DropPartitionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionName = builder.partitionName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -36,11 +46,6 @@ public class DropPartitionParam {
         return partitionName;
     }
 
-    public DropPartitionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.partitionName = builder.partitionName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String partitionName;
@@ -52,17 +57,20 @@ public class DropPartitionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withPartitionName(String partitionName) {
+        public Builder withPartitionName(@Nonnull String partitionName) {
             this.partitionName = partitionName;
             return this;
         }
 
-        public DropPartitionParam build() {
+        public DropPartitionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(partitionName, "Partition name");
+
             return new DropPartitionParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/partition/GetPartitionStatisticsParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for get partition statistics RPC operation
  *
@@ -28,6 +33,11 @@ public class GetPartitionStatisticsParam {
     private final String collectionName;
     private final String partitionName;
 
+    private GetPartitionStatisticsParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionName = builder.partitionName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -36,11 +46,6 @@ public class GetPartitionStatisticsParam {
         return partitionName;
     }
 
-    public GetPartitionStatisticsParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.partitionName = builder.partitionName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String partitionName;
@@ -52,17 +57,20 @@ public class GetPartitionStatisticsParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withPartitionName(String partitionName) {
+        public Builder withPartitionName(@Nonnull String partitionName) {
             this.partitionName = partitionName;
             return this;
         }
 
-        public GetPartitionStatisticsParam build() {
+        public GetPartitionStatisticsParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(partitionName, "Partition name");
+
             return new GetPartitionStatisticsParam(this);
         }
     }

+ 16 - 8
src/main/java/io/milvus/param/partition/HasPartitionParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for has partition RPC operation
  *
@@ -28,6 +33,11 @@ public class HasPartitionParam {
     private final String collectionName;
     private final String partitionName;
 
+    private HasPartitionParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionName = builder.partitionName;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -36,11 +46,6 @@ public class HasPartitionParam {
         return partitionName;
     }
 
-    public HasPartitionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.partitionName = builder.partitionName;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String partitionName;
@@ -52,17 +57,20 @@ public class HasPartitionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withPartitionName(String partitionName) {
+        public Builder withPartitionName(@Nonnull String partitionName) {
             this.partitionName = partitionName;
             return this;
         }
 
-        public HasPartitionParam build() {
+        public HasPartitionParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+            ParamUtils.CheckNullEmptyString(partitionName, "Partition name");
+
             return new HasPartitionParam(this);
         }
     }

+ 23 - 8
src/main/java/io/milvus/param/partition/LoadPartitionsParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for load partitions RPC operation
  *
@@ -28,6 +33,11 @@ public class LoadPartitionsParam {
     private final String collectionName;
     private final String[] partitionNames;
 
+    private LoadPartitionsParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionNames = builder.partitionNames;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -36,11 +46,6 @@ public class LoadPartitionsParam {
         return partitionNames;
     }
 
-    public LoadPartitionsParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.partitionNames = builder.partitionNames;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String[] partitionNames;
@@ -52,17 +57,27 @@ public class LoadPartitionsParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withPartitionNames(String[] partitionNames) {
+        public Builder withPartitionNames(@Nonnull String[] partitionNames) {
             this.partitionNames = partitionNames;
             return this;
         }
 
-        public LoadPartitionsParam build() {
+        public LoadPartitionsParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
+            if (partitionNames == null || partitionNames.length == 0) {
+                throw new ParamException("Partition names cannot be empty");
+            }
+
+            for (String name : partitionNames) {
+                ParamUtils.CheckNullEmptyString(name, "Partition name");
+            }
+
             return new LoadPartitionsParam(this);
         }
     }

+ 23 - 8
src/main/java/io/milvus/param/partition/ReleasePartitionsParam.java

@@ -19,6 +19,11 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params release partitions RPC operation
  *
@@ -28,6 +33,11 @@ public class ReleasePartitionsParam {
     private final String collectionName;
     private final String[] partitionNames;
 
+    private ReleasePartitionsParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionNames = builder.partitionNames;
+    }
+
     public String getCollectionName() {
         return collectionName;
     }
@@ -36,11 +46,6 @@ public class ReleasePartitionsParam {
         return partitionNames;
     }
 
-    public ReleasePartitionsParam(Builder builder) {
-        this.collectionName = builder.collectionName;
-        this.partitionNames = builder.partitionNames;
-    }
-
     public static final class Builder {
         private String collectionName;
         private String[] partitionNames;
@@ -52,17 +57,27 @@ public class ReleasePartitionsParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public Builder withPartitionNames(String[] partitionNames) {
+        public Builder withPartitionNames(@Nonnull String[] partitionNames) {
             this.partitionNames = partitionNames;
             return this;
         }
 
-        public ReleasePartitionsParam build() {
+        public ReleasePartitionsParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
+            if (partitionNames == null || partitionNames.length == 0) {
+                throw new ParamException("Partition names cannot be empty");
+            }
+
+            for (String name : partitionNames) {
+                ParamUtils.CheckNullEmptyString(name, "Partition name");
+            }
+
             return new ReleasePartitionsParam(this);
         }
     }

+ 15 - 9
src/main/java/io/milvus/param/partition/ShowPartitionParam.java → src/main/java/io/milvus/param/partition/ShowPartitionsParam.java

@@ -19,21 +19,25 @@
 
 package io.milvus.param.partition;
 
+import io.milvus.exception.ParamException;
+import io.milvus.param.ParamUtils;
+
+import javax.annotation.Nonnull;
+
 /**
  * Params for show partition RPC operation
  *
  * @author changzechuan
  */
-public class ShowPartitionParam {
+public class ShowPartitionsParam {
     private final String collectionName;
 
-    public String getCollectionName() {
-        return collectionName;
+    private ShowPartitionsParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
     }
 
-
-    public ShowPartitionParam(Builder builder) {
-        this.collectionName = builder.collectionName;
+    public String getCollectionName() {
+        return collectionName;
     }
 
     public static final class Builder {
@@ -46,13 +50,15 @@ public class ShowPartitionParam {
             return new Builder();
         }
 
-        public Builder withCollectionName(String collectionName) {
+        public Builder withCollectionName(@Nonnull String collectionName) {
             this.collectionName = collectionName;
             return this;
         }
 
-        public ShowPartitionParam build() {
-            return new ShowPartitionParam(this);
+        public ShowPartitionsParam build() throws ParamException {
+            ParamUtils.CheckNullEmptyString(collectionName, "Collection name");
+
+            return new ShowPartitionsParam(this);
         }
     }
 }

+ 242 - 0
src/test/java/io/milvus/client/MilvusClientDockerTest.java

@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package io.milvus.client;
+
+import io.milvus.grpc.DataType;
+import io.milvus.grpc.FlushResponse;
+import io.milvus.grpc.MutationResult;
+import io.milvus.grpc.SearchResults;
+import io.milvus.param.*;
+import io.milvus.param.collection.CreateCollectionParam;
+import io.milvus.param.collection.DropCollectionParam;
+import io.milvus.param.collection.FieldType;
+import io.milvus.param.collection.LoadCollectionParam;
+import io.milvus.param.dml.InsertParam;
+import io.milvus.param.dml.SearchParam;
+import org.apache.commons.text.RandomStringGenerator;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.*;
+
+import static org.junit.Assert.assertEquals;
+
+public class MilvusClientDockerTest {
+    private static final Logger logger = LogManager.getLogger("MilvusClientTest");
+    private static MilvusClient client;
+    private static RandomStringGenerator generator;
+    private int dimension = 128;
+    private static final Boolean useDockerCompose = Boolean.FALSE;
+
+    private static void startDockerContainer() {
+        if (!useDockerCompose) {
+            return;
+        }
+
+        // start the test container
+        Runtime runtime = Runtime.getRuntime();
+        String bashCommand = "docker-compose up -d";
+
+        try {
+            logger.debug(bashCommand);
+            Process pro = runtime.exec(bashCommand);
+            int status = pro.waitFor();
+            if (status != 0) {
+                logger.error("Failed to start docker compose, status " + status);
+            }
+        } catch (Throwable t) {
+            logger.error("Failed to execute docker compose up", t);
+        }
+    }
+
+    private static void stopDockerContainer() {
+        if (!useDockerCompose) {
+            return;
+        }
+
+        // stop all test dockers
+        Runtime runtime = Runtime.getRuntime();
+        String bashCommand = "docker-compose down";
+
+        try {
+            logger.debug(bashCommand);
+            Process pro = runtime.exec(bashCommand);
+            int status = pro.waitFor();
+            if (status != 0) {
+                logger.error("Failed to stop test docker containers" + pro.getOutputStream().toString());
+            }
+        } catch (Throwable t) {
+            logger.error("Failed to execute docker compose down", t);
+        }
+
+        // clean up log dir
+        runtime = Runtime.getRuntime();
+        bashCommand = "docker-compose rm";
+
+        try {
+            logger.debug(bashCommand);
+            Process pro = runtime.exec(bashCommand);
+            int status = pro.waitFor();
+            if (status != 0) {
+                logger.error("Failed to clean up test docker containers" + pro.getOutputStream().toString());
+            }
+
+            logger.error("Clean up volume directory of Docker");
+            FileUtils.deleteDirectory("volumes");
+        } catch (Throwable t) {
+            logger.error("Failed to remove docker com", t);
+        }
+    }
+
+    @BeforeClass
+    public static void setUp() {
+        startDockerContainer();
+
+        ConnectParam connectParam = connectParamBuilder().build();
+        client = new MilvusServiceClient(connectParam);
+        generator = new RandomStringGenerator.Builder().withinRange('a', 'z').build();
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        if (client != null) {
+            client.close();
+        }
+
+        stopDockerContainer();
+    }
+
+    protected static ConnectParam.Builder connectParamBuilder() {
+        return connectParamBuilder("localhost", 19530);
+    }
+
+    private static ConnectParam.Builder connectParamBuilder(String host, int port) {
+        return ConnectParam.Builder.newBuilder().withHost(host).withPort(port);
+    }
+
+    private static void checkR(R<?> r) {
+        if (r.getStatus() != R.Status.Success.getCode()) {
+            logger.error("Error code: {}" + r.getMessage(), r.getStatus());
+        }
+    }
+
+    @Test
+    public void testMainWorkflow() {
+        String randomCollectionName = generator.generate(10);
+
+        // collection schema
+        String field1Name = "field1";
+        String field2Name = "field2";
+        FieldType[] fieldTypes = new FieldType[2];
+        fieldTypes[0] = FieldType.Builder.newBuilder().withFieldID(0l)
+                .withPrimaryKey(true)
+                .withDataType(DataType.Int64)
+                .withName(field1Name)
+                .withDescription("hello")
+                .build();
+
+        fieldTypes[1] = FieldType.Builder.newBuilder().withFieldID(1l)
+                .withDataType(DataType.FloatVector)
+                .withName(field2Name)
+                .withDescription("world")
+                .withDimension(dimension)
+                .build();
+
+        // create collection
+        CreateCollectionParam createParam = CreateCollectionParam.Builder.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withDescription("test")
+                .withFieldTypes(fieldTypes)
+                .build();
+
+        R<RpcStatus> createR = client.createCollection(createParam);
+        assertEquals(createR.getStatus().intValue(), R.Status.Success.getCode());
+
+        // insert data
+        List<Long> ids = new ArrayList<>();
+        List<List<Float>> vectors = new ArrayList<>();
+
+        Random ran=new Random();
+        for (Long i = 0L; i < 10000; ++i) {
+            ids.add(i + 100L);
+            List<Float> vector = new ArrayList<>();
+            for (int d = 0; d < dimension; ++d) {
+                vector.add(ran.nextFloat());
+            }
+            vectors.add(vector);
+        }
+
+        List<InsertParam.Field> fields = new ArrayList<>();
+        fields.add(new InsertParam.Field(field1Name, DataType.Int64, ids));
+        fields.add(new InsertParam.Field(field2Name, DataType.FloatVector, vectors));
+
+        InsertParam insertParam = InsertParam.Builder
+                .newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withFields(fields)
+                .build();
+
+        R<MutationResult> insertR = client.insert(insertParam);
+        assertEquals(insertR.getStatus().intValue(), R.Status.Success.getCode());
+
+        // flush
+        R<FlushResponse> flushR = client.flush(randomCollectionName);
+        assertEquals(flushR.getStatus().intValue(), R.Status.Success.getCode());
+
+        // load collection
+        R<RpcStatus> loadR = client.loadCollection(LoadCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName(randomCollectionName)
+                .build());
+        assertEquals(loadR.getStatus().intValue(), R.Status.Success.getCode());
+
+        // search
+        List<Float> vector = new ArrayList<>();
+        for (int i = 0; i < 2; ++i) {
+            vector.add(ran.nextFloat());
+        }
+
+        List<String> outFields = Collections.singletonList(field1Name);
+        SearchParam searchParam = SearchParam.Builder.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .withMetricType(MetricType.L2)
+                .withOutFields(outFields)
+                .withTopK(5)
+                .withVectors(Collections.singletonList(vector))
+                .withVectorFieldName(field2Name)
+                .build();
+
+
+        R<SearchResults> searchR = client.search(searchParam);
+        assertEquals(searchR.getStatus().intValue(), R.Status.Success.getCode());
+
+        // drop collection
+        DropCollectionParam dropParam = DropCollectionParam.Builder.newBuilder()
+                .withCollectionName(randomCollectionName)
+                .build();
+
+        R<RpcStatus> deleteR = client.dropCollection(dropParam);
+        assertEquals(deleteR.getStatus().intValue(), R.Status.Success.getCode());
+    }
+}

+ 1829 - 39
src/test/java/io/milvus/client/MilvusServiceClientTest.java

@@ -1,28 +1,49 @@
-package io.milvus.client;
-
-import io.milvus.grpc.FlushResponse;
-import io.milvus.grpc.DataType;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 
-import io.milvus.param.RpcStatus;
-import io.milvus.param.collection.CreateCollectionParam;
-import io.milvus.param.collection.HasCollectionParam;
-import io.milvus.param.collection.FieldType;
-import io.milvus.param.ConnectParam;
-import io.milvus.param.R;
+package io.milvus.client;
 
+import io.milvus.exception.ParamException;
+import io.milvus.grpc.*;
+import io.milvus.param.*;
+import io.milvus.param.alias.AlterAliasParam;
+import io.milvus.param.alias.CreateAliasParam;
+import io.milvus.param.alias.DropAliasParam;
+import io.milvus.param.collection.*;
+import io.milvus.param.dml.*;
+import io.milvus.param.index.*;
+import io.milvus.param.partition.*;
 import io.milvus.server.MockMilvusServer;
 import io.milvus.server.MockMilvusServerImpl;
-
 import org.junit.jupiter.api.Test;
 
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import static org.junit.jupiter.api.Assertions.*;
 
 class MilvusServiceClientTest {
     private String testHost = "localhost";
     private int testPort = 53019;
 
-    private MockMilvusServer mockServer;
-
     private MockMilvusServer startServer() {
         MockMilvusServer mockServer = new MockMilvusServer(testPort, new MockMilvusServerImpl());
         mockServer.start();
@@ -38,6 +59,77 @@ class MilvusServiceClientTest {
         return milvusClient;
     }
 
+    @Test
+    void createCollectionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            FieldType.Builder.newBuilder()
+                    .withName("")
+                    .withDataType(DataType.Int64)
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            FieldType.Builder.newBuilder()
+                    .withName("userID")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            FieldType.Builder.newBuilder()
+                    .withName("userID")
+                    .withDataType(DataType.FloatVector)
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withShardsNum(2)
+                    .build();
+        });
+
+        FieldType[] fieldTypes = new FieldType[1];
+        FieldType fieldType1 = FieldType.Builder.newBuilder()
+                .withName("userID")
+                .withDescription("userId")
+                .withDataType(DataType.Int64)
+                .withAutoID(true)
+                .withPrimaryKey(true)
+                .build();
+        fieldTypes[0] = fieldType1;
+
+        assertThrows(ParamException.class, () -> {
+            CreateCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withShardsNum(2)
+                    .withFieldTypes(fieldTypes)
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withShardsNum(0)
+                    .withFieldTypes(fieldTypes)
+                    .build();
+        });
+
+        fieldTypes[0] = null;
+        assertThrows(ParamException.class, () -> {
+            CreateCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withShardsNum(0)
+                    .withFieldTypes(fieldTypes)
+                    .build();
+        });
+    }
+
+
     @Test
     void createCollection() {
         MilvusServiceClient client = startClient();
@@ -48,42 +140,107 @@ class MilvusServiceClientTest {
                 .withDescription("userId")
                 .withDataType(DataType.Int64)
                 .withAutoID(true)
-                .withPrimaryKey(true).build();
+                .withPrimaryKey(true)
+                .build();
         fieldTypes[0] = fieldType1;
 
-        // test return error with illegal input
-        R<RpcStatus> resp = client.createCollection(CreateCollectionParam.Builder
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return error with null param
+        R<RpcStatus> resp = client.createCollection(null);
+        assertEquals(R.Status.ParamError.getCode(), resp.getStatus());
+
+        // test return ok with correct input
+        resp = client.createCollection(CreateCollectionParam.Builder
                 .newBuilder()
                 .withCollectionName("collection1")
                 .withShardsNum(2)
+                .withFieldTypes(fieldTypes)
                 .build());
-        assertEquals(R.Status.ParamError.getCode(), resp.getStatus());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
 
+        // stop mock server
+        server.stop();
+
+        // test return error without server
         resp = client.createCollection(CreateCollectionParam.Builder
                 .newBuilder()
-                .withCollectionName("")
+                .withCollectionName("collection1")
                 .withShardsNum(2)
                 .withFieldTypes(fieldTypes)
                 .build());
-        assertEquals(R.Status.ParamError.getCode(), resp.getStatus());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
 
-        resp = client.createCollection(CreateCollectionParam.Builder
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.createCollection(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void describeCollectionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DescribeCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void describeCollection() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<DescribeCollectionResponse> resp = client.describeCollection(DescribeCollectionParam.Builder
                 .newBuilder()
                 .withCollectionName("collection1")
-                .withShardsNum(0)
-                .withFieldTypes(fieldTypes)
                 .build());
-        assertEquals(R.Status.ParamError.getCode(), resp.getStatus());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.describeCollection(DescribeCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.describeCollection(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void dropCollectionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DropCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void dropCollection() {
+        MilvusServiceClient client = startClient();
 
         // start mock server
         MockMilvusServer server = startServer();
 
         // test return ok with correct input
-        resp = client.createCollection(CreateCollectionParam.Builder
+        R<RpcStatus> resp = client.dropCollection(DropCollectionParam.Builder
                 .newBuilder()
                 .withCollectionName("collection1")
-                .withShardsNum(2)
-                .withFieldTypes(fieldTypes)
                 .build());
         assertEquals(R.Status.Success.getCode(), resp.getStatus());
 
@@ -91,31 +248,79 @@ class MilvusServiceClientTest {
         server.stop();
 
         // test return error without server
-        resp = client.createCollection(CreateCollectionParam.Builder
+        resp = client.dropCollection(DropCollectionParam.Builder
                 .newBuilder()
                 .withCollectionName("collection1")
-                .withShardsNum(2)
-                .withFieldTypes(fieldTypes)
                 .build());
         assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.dropCollection(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
     }
 
     @Test
-    void hasCollection() {
+    void getCollectionStatisticsParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            GetCollectionStatisticsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void getCollectionStatistics() {
         MilvusServiceClient client = startClient();
 
-        // test return error with illegal input
-        R<Boolean> resp = client.hasCollection(HasCollectionParam.Builder
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<GetCollectionStatisticsResponse> resp = client.getCollectionStatistics(GetCollectionStatisticsParam.Builder
                 .newBuilder()
-                .withCollectionName("")
+                .withCollectionName("collection1")
                 .build());
-        assertEquals(R.Status.ParamError.getCode(), resp.getStatus());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.getCollectionStatistics(GetCollectionStatisticsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.getCollectionStatistics(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void hasCollectionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            HasCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void hasCollection() {
+        MilvusServiceClient client = startClient();
 
         // start mock server
         MockMilvusServer server = startServer();
 
         // test return ok with correct input
-        resp = client.hasCollection(HasCollectionParam.Builder
+        R<Boolean> resp = client.hasCollection(HasCollectionParam.Builder
                 .newBuilder()
                 .withCollectionName("collection1")
                 .build());
@@ -130,21 +335,178 @@ class MilvusServiceClientTest {
                 .withCollectionName("collection1")
                 .build());
         assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.hasCollection(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void loadCollectionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            LoadCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void loadCollection() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.loadCollection(LoadCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.loadCollection(LoadCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.loadCollection(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void releaseCollectionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            ReleaseCollectionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void releaseCollection() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.releaseCollection(ReleaseCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.releaseCollection(ReleaseCollectionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.releaseCollection(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void showCollectionsParam() {
+        // test throw exception with illegal input
+        String[] names = new String[1];
+        names[0] = null;
+        assertThrows(ParamException.class, () -> {
+            ShowCollectionsParam.Builder
+                    .newBuilder()
+                    .withCollectionNames(names)
+                    .build();
+        });
+
+        names[0] = "";
+        assertThrows(ParamException.class, () -> {
+            ShowCollectionsParam.Builder
+                    .newBuilder()
+                    .withCollectionNames(names)
+                    .build();
+        });
+
+        names[0] = "collection1";
+        ShowCollectionsParam param = ShowCollectionsParam.Builder
+                .newBuilder()
+                .withCollectionNames(names)
+                .build();
+        assertEquals(param.getShowType(), ShowType.InMemory);
+    }
+
+    @Test
+    void showCollections() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        String[] names = new String[2];
+        names[0] = "collection1";
+        names[1] = "collection2";
+        R<ShowCollectionsResponse> resp = client.showCollections(ShowCollectionsParam.Builder
+                .newBuilder()
+                .withCollectionNames(names)
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.showCollections(ShowCollectionsParam.Builder
+                .newBuilder()
+                .withCollectionNames(names)
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.showCollections(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
     }
 
     @Test
     void flush() {
         MilvusServiceClient client = startClient();
 
-        // test return error with illegal input
-        R<FlushResponse> resp = client.flush("");
-        assertEquals(R.Status.ParamError.getCode(), resp.getStatus());
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            client.flush("");
+        });
 
         // start mock server
         MockMilvusServer server = startServer();
 
         // test return ok with correct input
-        resp = client.flush("collection1");
+        R<FlushResponse> resp = client.flush("collection1");
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        resp = client.flush("collection1", "db1");
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        List<String> collectionNames = new ArrayList<String>();
+        collectionNames.add("collection1");
+        resp = client.flush(collectionNames);
         assertEquals(R.Status.Success.getCode(), resp.getStatus());
 
         // stop mock server
@@ -153,5 +515,1433 @@ class MilvusServiceClientTest {
         // test return error without server
         resp = client.flush("collection1");
         assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.flush("collection1");
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void createPartitionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            CreatePartitionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionName("partition1")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreatePartitionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void createPartition() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.createPartition(CreatePartitionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.createPartition(CreatePartitionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.createPartition(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void dropPartitionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DropPartitionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionName("partition1")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            DropPartitionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void dropPartition() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.dropPartition(DropPartitionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.dropPartition(DropPartitionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.dropPartition(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void hasPartitionParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            HasPartitionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionName("partition1")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            HasPartitionParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void hasPartition() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<Boolean> resp = client.hasPartition(HasPartitionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.hasPartition(HasPartitionParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.hasPartition(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void loadPartitionsParam() {
+        // test throw exception with illegal input
+        String[] partitions = new String[1];
+        partitions[0] = "partition1";
+        assertThrows(ParamException.class, () -> {
+            LoadPartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionNames(partitions)
+                    .build();
+        });
+
+        partitions[0] = "";
+        assertThrows(ParamException.class, () -> {
+            LoadPartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .build();
+        });
+
+        partitions[0] = null;
+        assertThrows(ParamException.class, () -> {
+            LoadPartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .build();
+        });
+    }
+
+    @Test
+    void loadPartitions() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        String[] partitions = new String[1];
+        partitions[0] = "partition1";
+        R<RpcStatus> resp = client.loadPartitions(LoadPartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.loadPartitions(LoadPartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.loadPartitions(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void releasePartitionsParam() {
+        // test throw exception with illegal input
+        String[] partitions = new String[1];
+        partitions[0] = "partition1";
+        assertThrows(ParamException.class, () -> {
+            ReleasePartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionNames(partitions)
+                    .build();
+        });
+
+        partitions[0] = "";
+        assertThrows(ParamException.class, () -> {
+            ReleasePartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .build();
+        });
+
+        partitions[0] = null;
+        assertThrows(ParamException.class, () -> {
+            ReleasePartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .build();
+        });
+    }
+
+    @Test
+    void releasePartitions() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        String[] partitions = new String[1];
+        partitions[0] = "partition1";
+        R<RpcStatus> resp = client.releasePartitions(ReleasePartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.releasePartitions(ReleasePartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.releasePartitions(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void getPartitionStatisticsParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            GetPartitionStatisticsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionName("partition1")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            GetPartitionStatisticsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void getPartitionStatistics() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<GetPartitionStatisticsResponse> resp = client.getPartitionStatistics(GetPartitionStatisticsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.getPartitionStatistics(GetPartitionStatisticsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionName("partition1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.getPartitionStatistics(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void showPartitionsParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            ShowPartitionsParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void showPartitions() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<ShowPartitionsResponse> resp = client.showPartitions(ShowPartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.showPartitions(ShowPartitionsParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.showPartitions(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void createAliasParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            CreateAliasParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withAlias("alias1")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateAliasParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withAlias("")
+                    .build();
+        });
+    }
+
+    @Test
+    void createAlias() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.createAlias(CreateAliasParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withAlias("alias1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.createAlias(CreateAliasParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withAlias("alias1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.createAlias(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void dropAliasParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DropAliasParam.Builder
+                    .newBuilder()
+                    .withAlias("")
+                    .build();
+        });
+    }
+
+    @Test
+    void dropAlias() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.dropAlias(DropAliasParam.Builder
+                .newBuilder()
+                .withAlias("alias1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.dropAlias(DropAliasParam.Builder
+                .newBuilder()
+                .withAlias("alias1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.dropAlias(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void alterAliasParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            CreateAliasParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withAlias("alias1")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateAliasParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withAlias("")
+                    .build();
+        });
+    }
+
+    @Test
+    void alterAlias() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.alterAlias(AlterAliasParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withAlias("alias1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.alterAlias(AlterAliasParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withAlias("alias1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.alterAlias(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void createIndexParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            CreateIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withFieldName("field1")
+                    .withIndexType(IndexType.IVF_FLAT)
+                    .withMetricType(MetricType.L2)
+                    .withExtraParam("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("")
+                    .withIndexType(IndexType.IVF_FLAT)
+                    .withMetricType(MetricType.L2)
+                    .withExtraParam("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("field1")
+                    .withIndexType(IndexType.INVALID)
+                    .withMetricType(MetricType.L2)
+                    .withExtraParam("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("field1")
+                    .withIndexType(IndexType.IVF_FLAT)
+                    .withMetricType(MetricType.INVALID)
+                    .withExtraParam("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            CreateIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("field1")
+                    .withIndexType(IndexType.IVF_FLAT)
+                    .withMetricType(MetricType.L2)
+                    .withExtraParam("")
+                    .build();
+        });
+    }
+
+    @Test
+    void createIndex() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.createIndex(CreateIndexParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .withIndexType(IndexType.IVF_FLAT)
+                .withMetricType(MetricType.L2)
+                .withExtraParam("dummy")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.createIndex(CreateIndexParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .withIndexType(IndexType.IVF_FLAT)
+                .withMetricType(MetricType.L2)
+                .withExtraParam("dummy")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.createIndex(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void describeIndexParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DescribeIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            DescribeIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withFieldName("field1")
+                    .build();
+        });
+    }
+
+    @Test
+    void describeIndex() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<DescribeIndexResponse> resp = client.describeIndex(DescribeIndexParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.describeIndex(DescribeIndexParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.describeIndex(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void getIndexStateParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            GetIndexStateParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            GetIndexStateParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withFieldName("field1")
+                    .build();
+        });
+    }
+
+    @Test
+    void getIndexState() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<GetIndexStateResponse> resp = client.getIndexState(GetIndexStateParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.getIndexState(GetIndexStateParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.getIndexState(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void getIndexBuildProgressParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            GetIndexBuildProgressParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .build();
+        });
+    }
+
+    @Test
+    void getIndexBuildProgress() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<GetIndexBuildProgressResponse> resp = client.getIndexBuildProgress(GetIndexBuildProgressParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.getIndexBuildProgress(GetIndexBuildProgressParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.getIndexBuildProgress(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void dropIndexParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DropIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFieldName("")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            DropIndexParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withFieldName("field1")
+                    .build();
+        });
+    }
+
+    @Test
+    void dropIndex() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<RpcStatus> resp = client.dropIndex(DropIndexParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.dropIndex(DropIndexParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFieldName("field1")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.dropIndex(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void insertParam() {
+        // test throw exception with illegal input
+        List<InsertParam.Field> fields = new ArrayList<>();
+
+        // collection is empty
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // fields is empty
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // field is null
+        fields.add(null);
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // field name is empty
+        fields.clear();
+        List<Long> ids = new ArrayList<>();
+        fields.add(new InsertParam.Field("", DataType.Int64, ids));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // field row count is 0
+        fields.clear();
+        fields.add(new InsertParam.Field("field1", DataType.Int64, ids));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // field row count not equal
+        fields.clear();
+        ids.add(1L);
+        fields.add(new InsertParam.Field("field1", DataType.Int64, ids));
+        List<List<Float>> vectors = new ArrayList<>();
+        fields.add(new InsertParam.Field("field2", DataType.FloatVector, vectors));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // wrong type
+        fields.clear();
+        List<String> fakeVectors1 = new ArrayList<>();
+        fields.add(new InsertParam.Field("field2", DataType.FloatVector, fakeVectors1));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        fields.clear();
+        List<List<String>> fakeVectors2 = new ArrayList<>();
+        fields.add(new InsertParam.Field("field2", DataType.FloatVector, fakeVectors2));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        fields.clear();
+        fields.add(new InsertParam.Field("field2", DataType.BinaryVector, fakeVectors1));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        // vector dimension not equal
+        fields.clear();
+        List<Float> vector1 = Arrays.asList(0.1F);
+        List<Float> vector2 = Arrays.asList(0.1F, 0.2F);
+        vectors.add(vector1);
+        vectors.add(vector2);
+        fields.add(new InsertParam.Field("field1", DataType.FloatVector, vectors));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+
+        fields.clear();
+        ByteBuffer buf1 = ByteBuffer.allocate(1);
+        buf1.put((byte) 1);
+        ByteBuffer buf2 = ByteBuffer.allocate(2);
+        buf2.put((byte) 1);
+        buf2.put((byte) 2);
+        List<ByteBuffer> bvectors = Arrays.asList(buf1, buf2);
+        fields.add(new InsertParam.Field("field2", DataType.BinaryVector, bvectors));
+        assertThrows(ParamException.class, () -> {
+            InsertParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withFields(fields)
+                    .build();
+        });
+    }
+
+    @Test
+    void insert() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        List<InsertParam.Field> fields = new ArrayList<>();
+        List<Long> ids = Arrays.asList(1L);
+        fields.add(new InsertParam.Field("field1", DataType.Int64, ids));
+        R<MutationResult> resp = client.insert(InsertParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFields(fields)
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.insert(InsertParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withFields(fields)
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.insert(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void deleteParam() {
+        // test throw exception with illegal input
+        assertThrows(ParamException.class, () -> {
+            DeleteParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            DeleteParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withExpr("")
+                    .build();
+        });
+    }
+
+    @Test
+    void delete() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        R<MutationResult> resp = client.delete(DeleteParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withExpr("dummy")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.delete(DeleteParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withExpr("dummy")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.delete(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void searchParam() {
+        // test throw exception with illegal input
+        List<String> partitions = Arrays.asList("partition1");
+        List<String> outputFields = Arrays.asList("field2");
+        List<List<Float>> vectors = new ArrayList<>();
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("field1")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(vectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        List<Float> vector1 = Arrays.asList(0.1F);
+        vectors.add(vector1);
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("field1")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(vectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(vectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.INVALID)
+                    .withTopK(5)
+                    .withVectors(vectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(0)
+                    .withVectors(vectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        // vector type illegal
+        List<String> fakeVectors1 = Arrays.asList("fake");
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(fakeVectors1)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        List<List<String>> fakeVectors2 = Arrays.asList(fakeVectors1);
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(fakeVectors2)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        // vector dimension not equal
+        List<Float> vector2 = Arrays.asList(0.1F, 0.2F);
+        vectors.add(vector2);
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(vectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        ByteBuffer buf1 = ByteBuffer.allocate(1);
+        buf1.put((byte) 1);
+        ByteBuffer buf2 = ByteBuffer.allocate(2);
+        buf2.put((byte) 1);
+        buf2.put((byte) 2);
+        List<ByteBuffer> bvectors = Arrays.asList(buf1, buf2);
+        assertThrows(ParamException.class, () -> {
+            SearchParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withParams("dummy")
+                    .withOutFields(outputFields)
+                    .withVectorFieldName("")
+                    .withMetricType(MetricType.IP)
+                    .withTopK(5)
+                    .withVectors(bvectors)
+                    .withExpr("dummy")
+                    .build();
+        });
+    }
+
+    @Test
+    void search() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        List<String> partitions = Arrays.asList("partition1");
+        List<String> outputFields = Arrays.asList("field2");
+        List<List<Float>> vectors = new ArrayList<>();
+        List<Float> vector1 = Arrays.asList(0.1F);
+        vectors.add(vector1);
+
+        R<SearchResults> resp = client.search(SearchParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .withParams("dummy")
+                .withOutFields(outputFields)
+                .withVectorFieldName("field1")
+                .withMetricType(MetricType.IP)
+                .withTopK(5)
+                .withVectors(vectors)
+                .withExpr("dummy")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.search(SearchParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .withParams("dummy")
+                .withOutFields(outputFields)
+                .withVectorFieldName("field1")
+                .withMetricType(MetricType.IP)
+                .withTopK(5)
+                .withVectors(vectors)
+                .withExpr("dummy")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.search(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void queryParam() {
+        // test throw exception with illegal input
+        List<String> partitions = Arrays.asList("partition1");
+        List<String> outputFields = Arrays.asList("field2");
+        assertThrows(ParamException.class, () -> {
+            QueryParam.Builder
+                    .newBuilder()
+                    .withCollectionName("")
+                    .withPartitionNames(partitions)
+                    .withOutFields(outputFields)
+                    .withExpr("dummy")
+                    .build();
+        });
+
+        assertThrows(ParamException.class, () -> {
+            QueryParam.Builder
+                    .newBuilder()
+                    .withCollectionName("collection1")
+                    .withPartitionNames(partitions)
+                    .withOutFields(outputFields)
+                    .withExpr("")
+                    .build();
+        });
+    }
+
+    @Test
+    void query() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        List<String> partitions = Arrays.asList("partition1");
+        List<String> outputFields = Arrays.asList("field2");
+
+        R<QueryResults> resp = client.query(QueryParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .withOutFields(outputFields)
+                .withExpr("dummy")
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.query(QueryParam.Builder
+                .newBuilder()
+                .withCollectionName("collection1")
+                .withPartitionNames(partitions)
+                .withOutFields(outputFields)
+                .withExpr("dummy")
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.query(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
+    }
+
+    @Test
+    void calcDistanceParam() {
+        // test throw exception with illegal input
+        List<List<Float>> vectorsLeft = new ArrayList<>();
+        List<List<Float>> vectorsRight = new ArrayList<>();
+        List<Float> vector1 = Arrays.asList(0.1F);
+        List<Float> vector2 = Arrays.asList(0.1F);
+        vectorsLeft.add(vector1);
+        vectorsRight.add(vector2);
+
+        assertThrows(ParamException.class, () -> {
+            CalcDistanceParam.Builder
+                    .newBuilder()
+                    .withVectorsLeft(vectorsLeft)
+                    .withVectorsRight(vectorsRight)
+                    .withMetricType(MetricType.INVALID)
+                    .build();
+        });
+
+        vectorsLeft.clear();
+        assertThrows(ParamException.class, () -> {
+            CalcDistanceParam.Builder
+                    .newBuilder()
+                    .withVectorsLeft(vectorsLeft)
+                    .withVectorsRight(vectorsRight)
+                    .withMetricType(MetricType.IP)
+                    .build();
+        });
+
+        vectorsLeft.add(vector1);
+        vectorsRight.clear();
+        assertThrows(ParamException.class, () -> {
+            CalcDistanceParam.Builder
+                    .newBuilder()
+                    .withVectorsLeft(vectorsLeft)
+                    .withVectorsRight(vectorsRight)
+                    .withMetricType(MetricType.IP)
+                    .build();
+        });
+
+        // vector dimension not equal
+        vectorsRight.add(vector2);
+        List<Float> vector3 = Arrays.asList(0.1F, 0.2F);
+        vectorsLeft.add(vector3);
+        assertThrows(ParamException.class, () -> {
+            CalcDistanceParam.Builder
+                    .newBuilder()
+                    .withVectorsLeft(vectorsLeft)
+                    .withVectorsRight(vectorsRight)
+                    .withMetricType(MetricType.IP)
+                    .build();
+        });
+
+        vectorsLeft.clear();
+        vectorsLeft.add(vector1);
+        List<Float> vector4 = Arrays.asList(0.1F, 0.2F);
+        vectorsRight.add(vector4);
+        assertThrows(ParamException.class, () -> {
+            CalcDistanceParam.Builder
+                    .newBuilder()
+                    .withVectorsLeft(vectorsLeft)
+                    .withVectorsRight(vectorsRight)
+                    .withMetricType(MetricType.IP)
+                    .build();
+        });
+    }
+
+    @Test
+    void calcDistance() {
+        MilvusServiceClient client = startClient();
+
+        // start mock server
+        MockMilvusServer server = startServer();
+
+        // test return ok with correct input
+        List<List<Float>> vectorsLeft = new ArrayList<>();
+        List<List<Float>> vectorsRight = new ArrayList<>();
+        List<Float> vector1 = Arrays.asList(0.1F);
+        List<Float> vector2 = Arrays.asList(0.1F);
+        vectorsLeft.add(vector1);
+        vectorsRight.add(vector2);
+
+        R<CalcDistanceResults> resp = client.calcDistance(CalcDistanceParam.Builder
+                .newBuilder()
+                .withVectorsLeft(vectorsLeft)
+                .withVectorsRight(vectorsRight)
+                .withMetricType(MetricType.L2)
+                .build());
+        assertEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // stop mock server
+        server.stop();
+
+        // test return error without server
+        resp = client.calcDistance(CalcDistanceParam.Builder
+                .newBuilder()
+                .withVectorsLeft(vectorsLeft)
+                .withVectorsRight(vectorsRight)
+                .withMetricType(MetricType.L2)
+                .build());
+        assertNotEquals(R.Status.Success.getCode(), resp.getStatus());
+
+        // test return error when client channel is shutdown
+        client.close();
+        resp = client.calcDistance(null);
+        assertEquals(R.Status.ClientNotConnected.getCode(), resp.getStatus());
     }
 }

+ 21 - 7
src/test/java/io/milvus/server/MockMilvusServer.java

@@ -1,18 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 package io.milvus.server;
 
-import io.grpc.ManagedChannelBuilder;
 import io.grpc.Server;
 import io.grpc.ServerBuilder;
 import io.milvus.grpc.MilvusServiceGrpc;
-import io.milvus.param.ConnectParam;
-import io.milvus.param.R;
-
-import java.io.IOException;
-import java.util.concurrent.TimeUnit;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.concurrent.TimeUnit;
+
 public class MockMilvusServer {
     private static final Logger logger = LoggerFactory.getLogger(MockMilvusServer.class.getName());
 

+ 429 - 8
src/test/java/io/milvus/server/MockMilvusServerImpl.java

@@ -1,12 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 package io.milvus.server;
 
-import io.milvus.client.AbstractMilvusGrpcClient;
 import io.milvus.grpc.MilvusServiceGrpc;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class MockMilvusServerImpl extends MilvusServiceGrpc.MilvusServiceImplBase {
     private static final Logger logger = LoggerFactory.getLogger(MockMilvusServerImpl.class);
+    private io.milvus.grpc.Status respCreateCollection;
+    private io.milvus.grpc.DescribeCollectionResponse respDescribeCollection;
+    private io.milvus.grpc.Status respDropCollection;
+    private io.milvus.grpc.BoolResponse respHasCollection;
+    private io.milvus.grpc.GetCollectionStatisticsResponse respGetCollectionStatisticsResponse;
+    private io.milvus.grpc.Status respLoadCollection;
+    private io.milvus.grpc.Status respReleaseCollection;
+    private io.milvus.grpc.ShowCollectionsResponse respShowCollections;
+    private io.milvus.grpc.Status respCreatePartition;
+    private io.milvus.grpc.Status respDropPartition;
+    private io.milvus.grpc.BoolResponse respHasPartition;
+    private io.milvus.grpc.Status respLoadPartitions;
+    private io.milvus.grpc.Status respReleasePartitions;
+    private io.milvus.grpc.GetPartitionStatisticsResponse respGetPartitionStatistics;
+    private io.milvus.grpc.ShowPartitionsResponse respShowPartitions;
+    private io.milvus.grpc.Status respCreateAlias;
+    private io.milvus.grpc.Status respDropAlias;
+    private io.milvus.grpc.Status respAlterAlias;
+    private io.milvus.grpc.Status respCreateIndex;
+    private io.milvus.grpc.DescribeIndexResponse respDescribeIndex;
+    private io.milvus.grpc.GetIndexStateResponse respGetIndexState;
+    private io.milvus.grpc.GetIndexBuildProgressResponse respGetIndexBuildProgress;
+    private io.milvus.grpc.Status respDropIndex;
+    private io.milvus.grpc.MutationResult respInsert;
+    private io.milvus.grpc.MutationResult respDelete;
+    private io.milvus.grpc.SearchResults respSearch;
+    private io.milvus.grpc.FlushResponse respFlush;
+    private io.milvus.grpc.QueryResults respQuery;
+    private io.milvus.grpc.CalcDistanceResults respCalcDistance;
+    private io.milvus.grpc.GetPersistentSegmentInfoResponse respGetPersistentSegmentInfo;
+    private io.milvus.grpc.GetQuerySegmentInfoResponse respGetQuerySegmentInfo;
+    private io.milvus.grpc.GetMetricsResponse respGetMetrics;
 
     public MockMilvusServerImpl() {
     }
@@ -20,10 +70,47 @@ public class MockMilvusServerImpl extends MilvusServiceGrpc.MilvusServiceImplBas
         responseObserver.onCompleted();
     }
 
-    private io.milvus.grpc.Status respCreateCollection;
+    public void setCreateCollectionResponse(io.milvus.grpc.Status resp) {
+        respCreateCollection = resp;
+    }
+
+    @Override
+    public void describeCollection(io.milvus.grpc.DescribeCollectionRequest request,
+                                   io.grpc.stub.StreamObserver<io.milvus.grpc.DescribeCollectionResponse> responseObserver) {
+        logger.info("describeCollection() call");
+
+        responseObserver.onNext(respDescribeCollection);
+        responseObserver.onCompleted();
+    }
 
-    public void setCreateCollectionResponse(io.milvus.grpc.Status status) {
-        respCreateCollection = status;
+    public void setDescribeCollectionResponse(io.milvus.grpc.DescribeCollectionResponse resp) {
+        respDescribeCollection = resp;
+    }
+
+    @Override
+    public void dropCollection(io.milvus.grpc.DropCollectionRequest request,
+                               io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("dropCollection() call");
+
+        responseObserver.onNext(respDropCollection);
+        responseObserver.onCompleted();
+    }
+
+    public void setDropCollectionResponse(io.milvus.grpc.Status resp) {
+        respDropCollection = resp;
+    }
+
+    @Override
+    public void getCollectionStatistics(io.milvus.grpc.GetCollectionStatisticsRequest request,
+                                        io.grpc.stub.StreamObserver<io.milvus.grpc.GetCollectionStatisticsResponse> responseObserver) {
+        logger.info("getCollectionStatistics() call");
+
+        responseObserver.onNext(respGetCollectionStatisticsResponse);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetCollectionStatisticsResponse(io.milvus.grpc.GetCollectionStatisticsResponse resp) {
+        respGetCollectionStatisticsResponse = resp;
     }
 
     @Override
@@ -35,12 +122,283 @@ public class MockMilvusServerImpl extends MilvusServiceGrpc.MilvusServiceImplBas
         responseObserver.onCompleted();
     }
 
-    private io.milvus.grpc.BoolResponse respHasCollection;
-
     public void setHasCollectionResponse(io.milvus.grpc.BoolResponse resp) {
         respHasCollection = resp;
     }
 
+    @Override
+    public void loadCollection(io.milvus.grpc.LoadCollectionRequest request,
+                               io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("loadCollection() call");
+
+        responseObserver.onNext(respLoadCollection);
+        responseObserver.onCompleted();
+    }
+
+    public void setLoadCollectionResponse(io.milvus.grpc.Status resp) {
+        respLoadCollection = resp;
+    }
+
+    @Override
+    public void releaseCollection(io.milvus.grpc.ReleaseCollectionRequest request,
+                                  io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("releaseCollection() call");
+
+        responseObserver.onNext(respReleaseCollection);
+        responseObserver.onCompleted();
+    }
+
+    public void setReleaseCollectionResponse(io.milvus.grpc.Status resp) {
+        respReleaseCollection = resp;
+    }
+
+    @Override
+    public void showCollections(io.milvus.grpc.ShowCollectionsRequest request,
+                                io.grpc.stub.StreamObserver<io.milvus.grpc.ShowCollectionsResponse> responseObserver) {
+        logger.info("showCollections() call");
+
+        responseObserver.onNext(respShowCollections);
+        responseObserver.onCompleted();
+    }
+
+    public void setShowCollectionsResponse(io.milvus.grpc.ShowCollectionsResponse resp) {
+        respShowCollections = resp;
+    }
+
+    @Override
+    public void createPartition(io.milvus.grpc.CreatePartitionRequest request,
+                                io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("createPartition() call");
+
+        responseObserver.onNext(respCreatePartition);
+        responseObserver.onCompleted();
+    }
+
+    public void setCreatePartitionResponse(io.milvus.grpc.Status resp) {
+        respCreatePartition = resp;
+    }
+
+    @Override
+    public void dropPartition(io.milvus.grpc.DropPartitionRequest request,
+                              io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("dropPartition() call");
+
+        responseObserver.onNext(respDropPartition);
+        responseObserver.onCompleted();
+    }
+
+    public void setDropPartitionResponse(io.milvus.grpc.Status resp) {
+        respDropPartition = resp;
+    }
+
+    @Override
+    public void hasPartition(io.milvus.grpc.HasPartitionRequest request,
+                             io.grpc.stub.StreamObserver<io.milvus.grpc.BoolResponse> responseObserver) {
+        logger.info("hasPartition() call");
+
+        responseObserver.onNext(respHasPartition);
+        responseObserver.onCompleted();
+    }
+
+    public void setHasPartitionResponse(io.milvus.grpc.BoolResponse resp) {
+        respHasPartition = resp;
+    }
+
+    @Override
+    public void loadPartitions(io.milvus.grpc.LoadPartitionsRequest request,
+                               io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("loadPartitions() call");
+
+        responseObserver.onNext(respLoadPartitions);
+        responseObserver.onCompleted();
+    }
+
+    public void setLoadPartitionsResponse(io.milvus.grpc.Status resp) {
+        respLoadPartitions = resp;
+    }
+
+    @Override
+    public void releasePartitions(io.milvus.grpc.ReleasePartitionsRequest request,
+                                  io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("releasePartitions() call");
+
+        responseObserver.onNext(respReleasePartitions);
+        responseObserver.onCompleted();
+    }
+
+    public void setReleasePartitionsResponse(io.milvus.grpc.Status resp) {
+        respReleasePartitions = resp;
+    }
+
+    @Override
+    public void getPartitionStatistics(io.milvus.grpc.GetPartitionStatisticsRequest request,
+                                       io.grpc.stub.StreamObserver<io.milvus.grpc.GetPartitionStatisticsResponse> responseObserver) {
+        logger.info("getPartitionStatistics() call");
+
+        responseObserver.onNext(respGetPartitionStatistics);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetPartitionStatisticsResponse(io.milvus.grpc.GetPartitionStatisticsResponse resp) {
+        respGetPartitionStatistics = resp;
+    }
+
+    @Override
+    public void showPartitions(io.milvus.grpc.ShowPartitionsRequest request,
+                               io.grpc.stub.StreamObserver<io.milvus.grpc.ShowPartitionsResponse> responseObserver) {
+        logger.info("showPartitions() call");
+
+        responseObserver.onNext(respShowPartitions);
+        responseObserver.onCompleted();
+    }
+
+    public void setShowPartitionsResponse(io.milvus.grpc.ShowPartitionsResponse resp) {
+        respShowPartitions = resp;
+    }
+
+    @Override
+    public void createAlias(io.milvus.grpc.CreateAliasRequest request,
+                            io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("createAlias() call");
+
+        responseObserver.onNext(respCreateAlias);
+        responseObserver.onCompleted();
+    }
+
+    public void setCreateAliasResponse(io.milvus.grpc.Status resp) {
+        respCreateAlias = resp;
+    }
+
+    @Override
+    public void dropAlias(io.milvus.grpc.DropAliasRequest request,
+                          io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("dropAlias() call");
+
+        responseObserver.onNext(respDropAlias);
+        responseObserver.onCompleted();
+    }
+
+    public void setDropAliasResponse(io.milvus.grpc.Status resp) {
+        respDropAlias = resp;
+    }
+
+    @Override
+    public void alterAlias(io.milvus.grpc.AlterAliasRequest request,
+                           io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("alterAlias() call");
+
+        responseObserver.onNext(respAlterAlias);
+        responseObserver.onCompleted();
+    }
+
+    public void setAlterAliasResponse(io.milvus.grpc.Status resp) {
+        respAlterAlias = resp;
+    }
+
+    @Override
+    public void createIndex(io.milvus.grpc.CreateIndexRequest request,
+                            io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("createIndex() call");
+
+        responseObserver.onNext(respCreateIndex);
+        responseObserver.onCompleted();
+    }
+
+    public void setCreateIndexResponse(io.milvus.grpc.Status resp) {
+        respCreateIndex = resp;
+    }
+
+    @Override
+    public void describeIndex(io.milvus.grpc.DescribeIndexRequest request,
+                              io.grpc.stub.StreamObserver<io.milvus.grpc.DescribeIndexResponse> responseObserver) {
+        logger.info("describeIndex() call");
+
+        responseObserver.onNext(respDescribeIndex);
+        responseObserver.onCompleted();
+    }
+
+    public void setDescribeIndexResponse(io.milvus.grpc.DescribeIndexResponse resp) {
+        respDescribeIndex = resp;
+    }
+
+    @Override
+    public void getIndexState(io.milvus.grpc.GetIndexStateRequest request,
+                              io.grpc.stub.StreamObserver<io.milvus.grpc.GetIndexStateResponse> responseObserver) {
+        logger.info("getIndexState() call");
+
+        responseObserver.onNext(respGetIndexState);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetIndexStateResponse(io.milvus.grpc.GetIndexStateResponse resp) {
+        respGetIndexState = resp;
+    }
+
+    @Override
+    public void getIndexBuildProgress(io.milvus.grpc.GetIndexBuildProgressRequest request,
+                                      io.grpc.stub.StreamObserver<io.milvus.grpc.GetIndexBuildProgressResponse> responseObserver) {
+        logger.info("getIndexBuildProgress() call");
+
+        responseObserver.onNext(respGetIndexBuildProgress);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetIndexBuildProgressResponse(io.milvus.grpc.GetIndexBuildProgressResponse resp) {
+        respGetIndexBuildProgress = resp;
+    }
+
+    @Override
+    public void dropIndex(io.milvus.grpc.DropIndexRequest request,
+                          io.grpc.stub.StreamObserver<io.milvus.grpc.Status> responseObserver) {
+        logger.info("dropIndex() call");
+
+        responseObserver.onNext(respDropIndex);
+        responseObserver.onCompleted();
+    }
+
+    public void setDropIndexResponse(io.milvus.grpc.Status resp) {
+        respDropIndex = resp;
+    }
+
+    @Override
+    public void insert(io.milvus.grpc.InsertRequest request,
+                       io.grpc.stub.StreamObserver<io.milvus.grpc.MutationResult> responseObserver) {
+        logger.info("insert() call");
+
+        responseObserver.onNext(respInsert);
+        responseObserver.onCompleted();
+    }
+
+    public void setInsertResponse(io.milvus.grpc.MutationResult resp) {
+        respInsert = resp;
+    }
+
+    @Override
+    public void delete(io.milvus.grpc.DeleteRequest request,
+                       io.grpc.stub.StreamObserver<io.milvus.grpc.MutationResult> responseObserver) {
+        logger.info("delete() call");
+
+        responseObserver.onNext(respDelete);
+        responseObserver.onCompleted();
+    }
+
+    public void setDeleteResponse(io.milvus.grpc.MutationResult resp) {
+        respDelete = resp;
+    }
+
+    @Override
+    public void search(io.milvus.grpc.SearchRequest request,
+                       io.grpc.stub.StreamObserver<io.milvus.grpc.SearchResults> responseObserver) {
+        logger.info("search() call");
+
+        responseObserver.onNext(respSearch);
+        responseObserver.onCompleted();
+    }
+
+    public void setSearchResponse(io.milvus.grpc.SearchResults resp) {
+        respSearch = resp;
+    }
+
     @Override
     public void flush(io.milvus.grpc.FlushRequest request,
                       io.grpc.stub.StreamObserver<io.milvus.grpc.FlushResponse> responseObserver) {
@@ -50,9 +408,72 @@ public class MockMilvusServerImpl extends MilvusServiceGrpc.MilvusServiceImplBas
         responseObserver.onCompleted();
     }
 
-    private io.milvus.grpc.FlushResponse respFlush;
-
     public void setFlushResponse(io.milvus.grpc.FlushResponse resp) {
         respFlush = resp;
     }
+
+    @Override
+    public void query(io.milvus.grpc.QueryRequest request,
+                      io.grpc.stub.StreamObserver<io.milvus.grpc.QueryResults> responseObserver) {
+        logger.info("query() call");
+
+        responseObserver.onNext(respQuery);
+        responseObserver.onCompleted();
+    }
+
+    public void setQueryResponse(io.milvus.grpc.QueryResults resp) {
+        respQuery = resp;
+    }
+
+    @Override
+    public void calcDistance(io.milvus.grpc.CalcDistanceRequest request,
+                             io.grpc.stub.StreamObserver<io.milvus.grpc.CalcDistanceResults> responseObserver) {
+        logger.info("calcDistance() call");
+
+        responseObserver.onNext(respCalcDistance);
+        responseObserver.onCompleted();
+    }
+
+    public void setCalcDistanceResponse(io.milvus.grpc.CalcDistanceResults resp) {
+        respCalcDistance = resp;
+    }
+
+    @Override
+    public void getPersistentSegmentInfo(io.milvus.grpc.GetPersistentSegmentInfoRequest request,
+                                         io.grpc.stub.StreamObserver<io.milvus.grpc.GetPersistentSegmentInfoResponse> responseObserver) {
+        logger.info("getPersistentSegmentInfo() call");
+
+        responseObserver.onNext(respGetPersistentSegmentInfo);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetPersistentSegmentInfoResponse(io.milvus.grpc.GetPersistentSegmentInfoResponse resp) {
+        respGetPersistentSegmentInfo = resp;
+    }
+
+    @Override
+    public void getQuerySegmentInfo(io.milvus.grpc.GetQuerySegmentInfoRequest request,
+                                    io.grpc.stub.StreamObserver<io.milvus.grpc.GetQuerySegmentInfoResponse> responseObserver) {
+        logger.info("getQuerySegmentInfo() call");
+
+        responseObserver.onNext(respGetQuerySegmentInfo);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetQuerySegmentInfoResponse(io.milvus.grpc.GetQuerySegmentInfoResponse resp) {
+        respGetQuerySegmentInfo = resp;
+    }
+
+    @Override
+    public void getMetrics(io.milvus.grpc.GetMetricsRequest request,
+                           io.grpc.stub.StreamObserver<io.milvus.grpc.GetMetricsResponse> responseObserver) {
+        logger.info("getMetrics() call");
+
+        responseObserver.onNext(respGetMetrics);
+        responseObserver.onCompleted();
+    }
+
+    public void setGetMetricsResponse(io.milvus.grpc.GetMetricsResponse resp) {
+        respGetMetrics = resp;
+    }
 }