ソースを参照

Merge pull request #87 from youny626/0.7.0

SDK Version 0.7.0
Zhiru Zhu 5 年 前
コミット
5cfb6ebd0f

+ 7 - 0
CHANGELOG.md

@@ -1,5 +1,12 @@
 # Changelog     
 
+## milvus-sdk-java 0.7.0 (2020-04-15)
+
+## Feature
+---
+- \#261 - Integrate ANNOY into Milvus
+- \#1828 - Add searchAsync / createIndexAsync / insertAsync / flushAsync / compactAsync API
+
 ## milvus-sdk-java 0.6.0 (2020-03-31)
 
 ### Bug

+ 3 - 2
README.md

@@ -22,6 +22,7 @@ The following table shows compatibilities between Milvus and Java SDK.
    |     0.6.0      |    0.4.1    |
    |     0.7.0      |    0.5.0    |
    |     0.7.1      |    0.6.0    |
+   |     0.8.0      |    0.7.0    |
 
 ### Install Java SDK
 
@@ -33,14 +34,14 @@ You can use **Apache Maven** or **Gradle**/**Grails** to download the SDK.
         <dependency>
             <groupId>io.milvus</groupId>
             <artifactId>milvus-sdk-java</artifactId>
-            <version>0.6.0</version>
+            <version>0.7.0</version>
         </dependency>
        ```
 
    - Gradle/Grails
 
         ```gradle
-        compile 'io.milvus:milvus-sdk-java:0.6.0'
+        compile 'io.milvus:milvus-sdk-java:0.7.0'
         ```
 
 ### Examples

+ 1 - 1
examples/pom.xml

@@ -63,7 +63,7 @@
         <dependency>
             <groupId>io.milvus</groupId>
             <artifactId>milvus-sdk-java</artifactId>
-            <version>0.6.0</version>
+            <version>0.7.0</version>
         </dependency>
         <dependency>
             <groupId>com.google.code.gson</groupId>

+ 1 - 1
pom.xml

@@ -25,7 +25,7 @@
 
     <groupId>io.milvus</groupId>
     <artifactId>milvus-sdk-java</artifactId>
-    <version>0.6.0</version>
+    <version>0.7.0</version>
     <packaging>jar</packaging>
 
     <name>io.milvus:milvus-sdk-java</name>

+ 7 - 3
src/main/java/io/milvus/client/Index.java

@@ -76,11 +76,12 @@ public class Index {
     }
 
     /**
-     * Optional. Default to empty <code>String</code>.
+     * Optional. Default to empty <code>String</code>. Index parameters are different for different
+     * index types. Refer to <a
+     * href="https://milvus.io/docs/v0.7.0/guides/milvus_operation.md">https://milvus.io/docs/v0.7.0/guides/milvus_operation.md</a>
+     * for more information.
      *
      * <pre>
-     * For different index type, index parameter is different accordingly, for example:
-     *
      * FLAT/IVFLAT/SQ8: {"nlist": 16384}
      * nlist range:[1, 999999]
      *
@@ -97,6 +98,9 @@ public class Index {
      * HNSW: {"M": 16, "efConstruction": 500}
      * M range:[5, 48]
      * efConstruction range:[100, 500]
+     *
+     * ANNOY: {"n_trees": 4}
+     * n_trees range: [1, 16384)
      * </pre>
      *
      * @param paramsInJson extra parameters in JSON format

+ 4 - 28
src/main/java/io/milvus/client/IndexType.java

@@ -23,34 +23,9 @@ import java.util.Arrays;
 import java.util.Optional;
 
 /**
- * Represents different types of indexing method to query the collection:
- *
- * <pre>
- *
- * 1. FLAT - Provides 100% accuracy for recalls. However, performance might be downgraded due to huge computation effort;
- *
- * 2. IVFLAT - K-means based similarity search which is balanced between accuracy and performance;
- *
- * 3. IVF_SQ8 - Vector indexing that adopts a scalar quantization strategy that significantly reduces the size of a
- * vector (by about 3/4), thus improving the overall throughput of vector processing;
- *
- * 4. RNSG - NSG (Navigating Spreading-out Graph) is a graph-base search algorithm that a) lowers the average
- * out-degree of the graph for fast traversal; b) shortens the search path; c) reduces the index
- * size; d) lowers the indexing complexity. Extensive tests show that NSG can achieve very high
- * search performance at high precision, and needs much less memory. Compared to non-graph-based
- * algorithms, it is faster to achieve the same search precision.
- *
- * 5. IVF_SQ8_H - An enhanced index algorithm of IVF_SQ8. It supports hybrid computation on both CPU and GPU,
- * which significantly improves the search performance. To use this index type, make sure both cpu and gpu are added as
- * resources for search usage in the Milvus configuration file.
- *
- * 6. IVF_PQ - Indexing method built based on product quantization. The input vectors are split into distinct sub-vectors
- * which are then quantized separately. Vector size can be reduced to 1/8 or 1/16 of the original size.
- * If you choose this index, note that there is an inevicollection trade-off between memory and search accuracy.
- *
- * 7. HNSW - Hierarchical Navigable Small World graphs
- *
- * </pre>
+ * Represents different types of indexing method to query the collection. Refer to <a
+ * href="https://milvus.io/docs/v0.7.0/guides/index.md">https://milvus.io/docs/v0.7.0/guides/index.md</a>
+ * for more information.
  */
 public enum IndexType {
   INVALID(0),
@@ -61,6 +36,7 @@ public enum IndexType {
   IVF_SQ8_H(5),
   IVF_PQ(6),
   HNSW(11),
+  ANNOY(12),
 
   UNKNOWN(-1);
 

+ 7 - 3
src/main/java/io/milvus/client/MetricType.java

@@ -22,7 +22,11 @@ package io.milvus.client;
 import java.util.Arrays;
 import java.util.Optional;
 
-/** Represents available metric types */
+/**
+ * Represents available metric types. Refer to <a
+ * href="https://milvus.io/docs/v0.7.0/guides/metric.md">https://milvus.io/docs/v0.7.0/guides/metric.md</a>
+ * for more information.
+ */
 public enum MetricType {
   INVALID(0),
   /** Euclidean distance. For float vectors only */
@@ -35,9 +39,9 @@ public enum MetricType {
   JACCARD(4),
   /** Tanimoto distance. For binary vectors only */
   TANIMOTO(5),
-  /** Substructure: D(a, b) = 1 - N(a&b) / N(b). For binary vectors only */
+  /** Substructure. For binary vectors only */
   SUBSTRUCTURE(6),
-  /** Superstructure: D(a, b) = 1 - N(a&b) / N(a). For binary vectors only */
+  /** Superstructure. For binary vectors only */
   SUPERSTRUCTURE(7),
 
   UNKNOWN(-1);

+ 116 - 2
src/main/java/io/milvus/client/MilvusClient.java

@@ -19,14 +19,16 @@
 
 package io.milvus.client;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import java.util.List;
 
 /** The Milvus Client Interface */
 public interface MilvusClient {
 
-  String clientVersion = "0.6.0";
+  String clientVersion = "0.7.0";
 
-  /** @return current Milvus client version: 0.6.0 */
+  /** @return current Milvus client version: 0.7.0 */
   default String getClientVersion() {
     return clientVersion;
   }
@@ -133,6 +135,27 @@ public interface MilvusClient {
    */
   Response createIndex(Index index);
 
+  /**
+   * Creates index specified by <code>index</code> asynchronously
+   *
+   * @param index the <code>Index</code> object
+   *     <pre>
+   * example usage:
+   * <code>
+   * Index index = new Index.Builder(collectionName, IndexType.IVF_SQ8)
+   *                        .withParamsInJson("{\"nlist\": 16384}")
+   *                        .build();
+   * </code>
+   * </pre>
+   *
+   * @return a <code>ListenableFuture</code> object which holds the <code>Response</code>
+   * @see Index
+   * @see IndexType
+   * @see Response
+   * @see ListenableFuture
+   */
+  ListenableFuture<Response> createIndexAsync(Index index);
+
   /**
    * Creates a partition specified by <code>collectionName</code> and <code>tag</code>
    *
@@ -184,6 +207,29 @@ public interface MilvusClient {
    */
   InsertResponse insert(InsertParam insertParam);
 
+  /**
+   * Inserts data specified by <code>insertParam</code> asynchronously
+   *
+   * @param insertParam the <code>InsertParam</code> object
+   *     <pre>
+   * example usage:
+   * <code>
+   * InsertParam insertParam = new InsertParam.Builder(collectionName)
+   *                                          .withFloatVectors(floatVectors)
+   *                                          .withVectorIds(vectorIds)
+   *                                          .withPartitionTag(tag)
+   *                                          .build();
+   * </code>
+   * </pre>
+   *
+   * @return a <code>ListenableFuture</code> object which holds the <code>InsertResponse</code>
+   * @see InsertParam
+   * @see InsertResponse
+   * @see Response
+   * @see ListenableFuture
+   */
+  ListenableFuture<InsertResponse> insertAsync(InsertParam insertParam);
+
   /**
    * Searches vectors specified by <code>searchParam</code>
    *
@@ -208,6 +254,31 @@ public interface MilvusClient {
    */
   SearchResponse search(SearchParam searchParam);
 
+  /**
+   * Searches vectors specified by <code>searchParam</code> asynchronously
+   *
+   * @param searchParam the <code>SearchParam</code> object
+   *     <pre>
+   * example usage:
+   * <code>
+   * SearchParam searchParam = new SearchParam.Builder(collectionName)
+   *                                          .withFloatVectors(floatVectors)
+   *                                          .withTopK(topK)
+   *                                          .withPartitionTags(partitionTagsList)
+   *                                          .withParamsInJson("{\"nprobe\": 20}")
+   *                                          .build();
+   * </code>
+   * </pre>
+   *
+   * @return a <code>ListenableFuture</code> object which holds the <code>SearchResponse</code>
+   * @see SearchParam
+   * @see SearchResponse
+   * @see SearchResponse.QueryResult
+   * @see Response
+   * @see ListenableFuture
+   */
+  ListenableFuture<SearchResponse> searchAsync(SearchParam searchParam);
+
   /**
    * Searches vectors in specific files
    *
@@ -309,6 +380,7 @@ public interface MilvusClient {
    * Drops collection index
    *
    * @param collectionName collection to drop index of
+   * @return <code>Response</code>
    * @see Response
    */
   Response dropIndex(String collectionName);
@@ -319,6 +391,7 @@ public interface MilvusClient {
    * segment can be uniquely identified by its partition tag or segment name respectively.
    *
    * @param collectionName collection to show info from
+   * @return <code>ShowCollectionInfoResponse</code>
    * @see ShowCollectionInfoResponse
    * @see CollectionInfo
    * @see CollectionInfo.PartitionInfo
@@ -332,6 +405,7 @@ public interface MilvusClient {
    *
    * @param collectionName collection to get vector from
    * @param id vector id
+   * @return <code>GetVectorByIdResponse</code>
    * @see GetVectorByIdResponse
    * @see Response
    */
@@ -342,6 +416,7 @@ public interface MilvusClient {
    *
    * @param collectionName collection to get vector ids from
    * @param segmentName segment name
+   * @return <code>GetVectorIdsResponse</code>
    * @see GetVectorIdsResponse
    * @see Response
    */
@@ -352,6 +427,7 @@ public interface MilvusClient {
    *
    * @param collectionName collection to delete ids from
    * @param ids a <code>List</code> of vector ids to delete
+   * @return <code>Response</code>
    * @see Response
    */
   Response deleteByIds(String collectionName, List<Long> ids);
@@ -361,6 +437,7 @@ public interface MilvusClient {
    *
    * @param collectionName collection to delete id from
    * @param id vector id to delete
+   * @return <code>Response</code>
    * @see Response
    */
   Response deleteById(String collectionName, Long id);
@@ -370,26 +447,63 @@ public interface MilvusClient {
    * after <code>flush</code> returned
    *
    * @param collectionNames a <code>List</code> of collections to flush
+   * @return <code>Response</code>
    * @see Response
    */
   Response flush(List<String> collectionNames);
 
+  /**
+   * Flushes data in a list collections asynchronously. Newly inserted or modifications on data will
+   * be visible after <code>flush</code> returned
+   *
+   * @param collectionNames a <code>List</code> of collections to flush
+   * @return a <code>ListenableFuture</code> object which holds the <code>Response</code>
+   * @see Response
+   * @see ListenableFuture
+   */
+  ListenableFuture<Response> flushAsync(List<String> collectionNames);
+
   /**
    * Flushes data in a collection. Newly inserted or modifications on data will be visible after
    * <code>flush</code> returned
    *
    * @param collectionName name of collection to flush
+   * @return <code>Response</code>
    * @see Response
    */
   Response flush(String collectionName);
 
+  /**
+   * Flushes data in a collection asynchronously. Newly inserted or modifications on data will be
+   * visible after <code>flush</code> returned
+   *
+   * @param collectionName name of collection to flush
+   * @return a <code>ListenableFuture</code> object which holds the <code>Response</code>
+   * @see Response
+   * @see ListenableFuture
+   */
+  ListenableFuture<Response> flushAsync(String collectionName);
+
   /**
    * Compacts the collection, erasing deleted data from disk and rebuild index in background (if the
    * data size after compaction is still larger than indexFileSize). Data was only soft-deleted
    * until you call compact.
    *
    * @param collectionName name of collection to compact
+   * @return <code>Response</code>
    * @see Response
    */
   Response compact(String collectionName);
+
+  /**
+   * Compacts the collection asynchronously, erasing deleted data from disk and rebuild index in
+   * background (if the data size after compaction is still larger than indexFileSize). Data was
+   * only soft-deleted until you call compact.
+   *
+   * @param collectionName name of collection to compact
+   * @return a <code>ListenableFuture</code> object which holds the <code>Response</code>
+   * @see Response
+   * @see ListenableFuture
+   */
+  ListenableFuture<Response> compactAsync(String collectionName);
 }

+ 393 - 128
src/main/java/io/milvus/client/MilvusGrpcClient.java

@@ -19,11 +19,16 @@
 
 package io.milvus.client;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import com.google.protobuf.ByteString;
 import io.grpc.ConnectivityState;
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.StatusRuntimeException;
+import io.milvus.grpc.*;
 import org.apache.commons.collections4.ListUtils;
 
 import javax.annotation.Nonnull;
@@ -32,6 +37,7 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -45,7 +51,8 @@ public class MilvusGrpcClient implements MilvusClient {
   private static final String ANSI_BRIGHT_PURPLE = "\u001B[95m";
   private final String extraParamKey = "params";
   private ManagedChannel channel = null;
-  private io.milvus.grpc.MilvusServiceGrpc.MilvusServiceBlockingStub blockingStub = null;
+  private MilvusServiceGrpc.MilvusServiceBlockingStub blockingStub = null;
+  private MilvusServiceGrpc.MilvusServiceFutureStub futureStub = null;
 
   ////////////////////// Constructor //////////////////////
   public MilvusGrpcClient() {
@@ -100,7 +107,8 @@ public class MilvusGrpcClient implements MilvusClient {
         timeout -= checkFrequency;
       }
 
-      blockingStub = io.milvus.grpc.MilvusServiceGrpc.newBlockingStub(channel);
+      blockingStub = MilvusServiceGrpc.newBlockingStub(channel);
+      futureStub = MilvusServiceGrpc.newFutureStub(channel);
 
     } catch (Exception e) {
       if (!(e instanceof ConnectFailedException)) {
@@ -153,20 +161,20 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.TableSchema request =
-        io.milvus.grpc.TableSchema.newBuilder()
-            .setTableName(collectionMapping.getCollectionName())
+    CollectionSchema request =
+        CollectionSchema.newBuilder()
+            .setCollectionName(collectionMapping.getCollectionName())
             .setDimension(collectionMapping.getDimension())
             .setIndexFileSize(collectionMapping.getIndexFileSize())
             .setMetricType(collectionMapping.getMetricType().getVal())
             .build();
 
-    io.milvus.grpc.Status response;
+    Status response;
 
     try {
-      response = blockingStub.createTable(request);
+      response = blockingStub.createCollection(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Created collection successfully!\n{0}", collectionMapping.toString());
         return new Response(Response.Status.SUCCESS);
       } else if (response.getReason().contentEquals("Collection already exists")) {
@@ -194,14 +202,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new HasCollectionResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), false);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.BoolReply response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    BoolReply response;
 
     try {
-      response = blockingStub.hasTable(request);
+      response = blockingStub.hasCollection(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("hasCollection `{0}` = {1}", collectionName, response.getBoolReply());
         return new HasCollectionResponse(
             new Response(Response.Status.SUCCESS), response.getBoolReply());
@@ -228,14 +235,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.Status response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    Status response;
 
     try {
-      response = blockingStub.dropTable(request);
+      response = blockingStub.dropCollection(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Dropped collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -257,24 +263,21 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.KeyValuePair extraParam =
-        io.milvus.grpc.KeyValuePair.newBuilder()
-            .setKey(extraParamKey)
-            .setValue(index.getParamsInJson())
-            .build();
-    io.milvus.grpc.IndexParam request =
-        io.milvus.grpc.IndexParam.newBuilder()
-            .setTableName(index.getCollectionName())
+    KeyValuePair extraParam =
+        KeyValuePair.newBuilder().setKey(extraParamKey).setValue(index.getParamsInJson()).build();
+    IndexParam request =
+        IndexParam.newBuilder()
+            .setCollectionName(index.getCollectionName())
             .setIndexType(index.getIndexType().getVal())
             .addExtraParams(extraParam)
             .build();
 
-    io.milvus.grpc.Status response;
+    Status response;
 
     try {
       response = blockingStub.createIndex(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Created index successfully!\n{0}", index.toString());
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -288,6 +291,50 @@ public class MilvusGrpcClient implements MilvusClient {
     }
   }
 
+  @Override
+  public ListenableFuture<Response> createIndexAsync(@Nonnull Index index) {
+
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      return Futures.immediateFuture(new Response(Response.Status.CLIENT_NOT_CONNECTED));
+    }
+
+    KeyValuePair extraParam =
+        KeyValuePair.newBuilder().setKey(extraParamKey).setValue(index.getParamsInJson()).build();
+    IndexParam request =
+        IndexParam.newBuilder()
+            .setCollectionName(index.getCollectionName())
+            .setIndexType(index.getIndexType().getVal())
+            .addExtraParams(extraParam)
+            .build();
+
+    ListenableFuture<Status> response;
+
+    response = futureStub.createIndex(request);
+
+    Futures.addCallback(
+        response,
+        new FutureCallback<Status>() {
+          @Override
+          public void onSuccess(Status result) {
+            if (result.getErrorCode() == ErrorCode.SUCCESS) {
+              logInfo("Created index successfully!\n{0}", index.toString());
+            } else {
+              logSevere("CreateIndexAsync failed:\n{0}\n{1}", index.toString(), result.toString());
+            }
+          }
+
+          @Override
+          public void onFailure(Throwable t) {
+            logSevere("CreateIndexAsync failed:\n{0}", t.getMessage());
+          }
+        },
+        MoreExecutors.directExecutor());
+
+    return Futures.transform(
+        response, transformStatusToResponseFunc::apply, MoreExecutors.directExecutor());
+  }
+
   @Override
   public Response createPartition(String collectionName, String tag) {
 
@@ -296,15 +343,15 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.PartitionParam request =
-        io.milvus.grpc.PartitionParam.newBuilder().setTableName(collectionName).setTag(tag).build();
+    PartitionParam request =
+        PartitionParam.newBuilder().setCollectionName(collectionName).setTag(tag).build();
 
-    io.milvus.grpc.Status response;
+    Status response;
 
     try {
       response = blockingStub.createPartition(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Created partition `{0}` in collection `{1}` successfully!", tag, collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -329,14 +376,13 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.PartitionList response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    PartitionList response;
 
     try {
       response = blockingStub.showPartitions(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         logInfo(
             "Current partitions of collection {0}: {1}",
             collectionName, response.getPartitionTagArrayList());
@@ -365,14 +411,14 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.PartitionParam request =
-        io.milvus.grpc.PartitionParam.newBuilder().setTableName(collectionName).setTag(tag).build();
-    io.milvus.grpc.Status response;
+    PartitionParam request =
+        PartitionParam.newBuilder().setCollectionName(collectionName).setTag(tag).build();
+    Status response;
 
     try {
       response = blockingStub.dropPartition(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Dropped partition `{1}` in collection `{1}` successfully!", tag, collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -397,22 +443,22 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
     }
 
-    List<io.milvus.grpc.RowRecord> rowRecordList =
+    List<RowRecord> rowRecordList =
         buildRowRecordList(insertParam.getFloatVectors(), insertParam.getBinaryVectors());
 
     io.milvus.grpc.InsertParam request =
         io.milvus.grpc.InsertParam.newBuilder()
-            .setTableName(insertParam.getCollectionName())
+            .setCollectionName(insertParam.getCollectionName())
             .addAllRowRecordArray(rowRecordList)
             .addAllRowIdArray(insertParam.getVectorIds())
             .setPartitionTag(insertParam.getPartitionTag())
             .build();
-    io.milvus.grpc.VectorIds response;
+    VectorIds response;
 
     try {
       response = blockingStub.insert(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         logInfo(
             "Inserted {0} vectors to collection `{1}` successfully!",
             response.getVectorIdArrayCount(), insertParam.getCollectionName());
@@ -433,6 +479,69 @@ public class MilvusGrpcClient implements MilvusClient {
     }
   }
 
+  @Override
+  public ListenableFuture<InsertResponse> insertAsync(@Nonnull InsertParam insertParam) {
+
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      return Futures.immediateFuture(
+          new InsertResponse(
+              new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>()));
+    }
+
+    List<RowRecord> rowRecordList =
+        buildRowRecordList(insertParam.getFloatVectors(), insertParam.getBinaryVectors());
+
+    io.milvus.grpc.InsertParam request =
+        io.milvus.grpc.InsertParam.newBuilder()
+            .setCollectionName(insertParam.getCollectionName())
+            .addAllRowRecordArray(rowRecordList)
+            .addAllRowIdArray(insertParam.getVectorIds())
+            .setPartitionTag(insertParam.getPartitionTag())
+            .build();
+
+    ListenableFuture<VectorIds> response;
+
+    response = futureStub.insert(request);
+
+    Futures.addCallback(
+        response,
+        new FutureCallback<VectorIds>() {
+          @Override
+          public void onSuccess(VectorIds result) {
+            if (result.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
+              logInfo(
+                  "Inserted {0} vectors to collection `{1}` successfully!",
+                  result.getVectorIdArrayCount(), insertParam.getCollectionName());
+            } else {
+              logSevere("InsertAsync failed:\n{0}", result.getStatus().toString());
+            }
+          }
+
+          @Override
+          public void onFailure(Throwable t) {
+            logSevere("InsertAsync failed:\n{0}", t.getMessage());
+          }
+        },
+        MoreExecutors.directExecutor());
+
+    Function<VectorIds, InsertResponse> transformFunc =
+        vectorIds -> {
+          if (vectorIds.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
+            return new InsertResponse(
+                new Response(Response.Status.SUCCESS), vectorIds.getVectorIdArrayList());
+          } else {
+            return new InsertResponse(
+                new Response(
+                    Response.Status.valueOf(vectorIds.getStatus().getErrorCodeValue()),
+                    vectorIds.getStatus().getReason()),
+                new ArrayList<>());
+          }
+        };
+
+    return Futures.transform(response, transformFunc::apply, MoreExecutors.directExecutor());
+  }
+
   @Override
   public SearchResponse search(@Nonnull SearchParam searchParam) {
 
@@ -443,30 +552,30 @@ public class MilvusGrpcClient implements MilvusClient {
       return searchResponse;
     }
 
-    List<io.milvus.grpc.RowRecord> rowRecordList =
+    List<RowRecord> rowRecordList =
         buildRowRecordList(searchParam.getFloatVectors(), searchParam.getBinaryVectors());
 
-    io.milvus.grpc.KeyValuePair extraParam =
-        io.milvus.grpc.KeyValuePair.newBuilder()
+    KeyValuePair extraParam =
+        KeyValuePair.newBuilder()
             .setKey(extraParamKey)
             .setValue(searchParam.getParamsInJson())
             .build();
 
     io.milvus.grpc.SearchParam request =
         io.milvus.grpc.SearchParam.newBuilder()
-            .setTableName(searchParam.getCollectionName())
+            .setCollectionName(searchParam.getCollectionName())
             .addAllQueryRecordArray(rowRecordList)
             .addAllPartitionTagArray(searchParam.getPartitionTags())
             .setTopk(searchParam.getTopK())
             .addExtraParams(extraParam)
             .build();
 
-    io.milvus.grpc.TopKQueryResult response;
+    TopKQueryResult response;
 
     try {
       response = blockingStub.search(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         SearchResponse searchResponse = buildSearchResponse(response);
         searchResponse.setResponse(new Response(Response.Status.SUCCESS));
         logInfo(
@@ -490,6 +599,78 @@ public class MilvusGrpcClient implements MilvusClient {
     }
   }
 
+  @Override
+  public ListenableFuture<SearchResponse> searchAsync(@Nonnull SearchParam searchParam) {
+
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      SearchResponse searchResponse = new SearchResponse();
+      searchResponse.setResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED));
+      return Futures.immediateFuture(searchResponse);
+    }
+
+    List<RowRecord> rowRecordList =
+        buildRowRecordList(searchParam.getFloatVectors(), searchParam.getBinaryVectors());
+
+    KeyValuePair extraParam =
+        KeyValuePair.newBuilder()
+            .setKey(extraParamKey)
+            .setValue(searchParam.getParamsInJson())
+            .build();
+
+    io.milvus.grpc.SearchParam request =
+        io.milvus.grpc.SearchParam.newBuilder()
+            .setCollectionName(searchParam.getCollectionName())
+            .addAllQueryRecordArray(rowRecordList)
+            .addAllPartitionTagArray(searchParam.getPartitionTags())
+            .setTopk(searchParam.getTopK())
+            .addExtraParams(extraParam)
+            .build();
+
+    ListenableFuture<TopKQueryResult> response;
+
+    response = futureStub.search(request);
+
+    Futures.addCallback(
+        response,
+        new FutureCallback<TopKQueryResult>() {
+          @Override
+          public void onSuccess(TopKQueryResult result) {
+            if (result.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
+              logInfo(
+                  "SearchAsync completed successfully! Returned results for {0} queries",
+                  result.getRowNum());
+            } else {
+              logSevere("SearchAsync failed:\n{0}", result.getStatus().toString());
+            }
+          }
+
+          @Override
+          public void onFailure(Throwable t) {
+            logSevere("SearchAsync failed:\n{0}", t.getMessage());
+          }
+        },
+        MoreExecutors.directExecutor());
+
+    Function<TopKQueryResult, SearchResponse> transformFunc =
+        topKQueryResult -> {
+          if (topKQueryResult.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
+            SearchResponse searchResponse = buildSearchResponse(topKQueryResult);
+            searchResponse.setResponse(new Response(Response.Status.SUCCESS));
+            return searchResponse;
+          } else {
+            SearchResponse searchResponse = new SearchResponse();
+            searchResponse.setResponse(
+                new Response(
+                    Response.Status.valueOf(topKQueryResult.getStatus().getErrorCodeValue()),
+                    topKQueryResult.getStatus().getReason()));
+            return searchResponse;
+          }
+        };
+
+    return Futures.transform(response, transformFunc::apply, MoreExecutors.directExecutor());
+  }
+
   @Override
   public SearchResponse searchInFiles(
       @Nonnull List<String> fileIds, @Nonnull SearchParam searchParam) {
@@ -501,36 +682,36 @@ public class MilvusGrpcClient implements MilvusClient {
       return searchResponse;
     }
 
-    List<io.milvus.grpc.RowRecord> rowRecordList =
+    List<RowRecord> rowRecordList =
         buildRowRecordList(searchParam.getFloatVectors(), searchParam.getBinaryVectors());
 
-    io.milvus.grpc.KeyValuePair extraParam =
-        io.milvus.grpc.KeyValuePair.newBuilder()
+    KeyValuePair extraParam =
+        KeyValuePair.newBuilder()
             .setKey(extraParamKey)
             .setValue(searchParam.getParamsInJson())
             .build();
 
     io.milvus.grpc.SearchParam constructSearchParam =
         io.milvus.grpc.SearchParam.newBuilder()
-            .setTableName(searchParam.getCollectionName())
+            .setCollectionName(searchParam.getCollectionName())
             .addAllQueryRecordArray(rowRecordList)
             .addAllPartitionTagArray(searchParam.getPartitionTags())
             .setTopk(searchParam.getTopK())
             .addExtraParams(extraParam)
             .build();
 
-    io.milvus.grpc.SearchInFilesParam request =
-        io.milvus.grpc.SearchInFilesParam.newBuilder()
+    SearchInFilesParam request =
+        SearchInFilesParam.newBuilder()
             .addAllFileIdArray(fileIds)
             .setSearchParam(constructSearchParam)
             .build();
 
-    io.milvus.grpc.TopKQueryResult response;
+    TopKQueryResult response;
 
     try {
       response = blockingStub.searchInFiles(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         SearchResponse searchResponse = buildSearchResponse(response);
         searchResponse.setResponse(new Response(Response.Status.SUCCESS));
         logInfo(
@@ -564,16 +745,15 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.TableSchema response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    CollectionSchema response;
 
     try {
-      response = blockingStub.describeTable(request);
+      response = blockingStub.describeCollection(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         CollectionMapping collectionMapping =
-            new CollectionMapping.Builder(response.getTableName(), response.getDimension())
+            new CollectionMapping.Builder(response.getCollectionName(), response.getDimension())
                 .withIndexFileSize(response.getIndexFileSize())
                 .withMetricType(MetricType.valueOf(response.getMetricType()))
                 .build();
@@ -606,14 +786,14 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
     }
 
-    io.milvus.grpc.Command request = io.milvus.grpc.Command.newBuilder().setCmd("").build();
-    io.milvus.grpc.TableNameList response;
+    Command request = Command.newBuilder().setCmd("").build();
+    CollectionNameList response;
 
     try {
-      response = blockingStub.showTables(request);
+      response = blockingStub.showCollections(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        List<String> collectionNames = response.getTableNamesList();
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
+        List<String> collectionNames = response.getCollectionNamesList();
         logInfo("Current collections: {0}", collectionNames.toString());
         return new ShowCollectionsResponse(new Response(Response.Status.SUCCESS), collectionNames);
       } else {
@@ -640,15 +820,14 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), 0);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.TableRowCount response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    CollectionRowCount response;
 
     try {
-      response = blockingStub.countTable(request);
+      response = blockingStub.countCollection(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        long collectionRowCount = response.getTableRowCount();
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
+        long collectionRowCount = response.getCollectionRowCount();
         logInfo("Collection `{0}` has {1} rows", collectionName, collectionRowCount);
         return new GetCollectionRowCountResponse(
             new Response(Response.Status.SUCCESS), collectionRowCount);
@@ -686,13 +865,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.Command request = io.milvus.grpc.Command.newBuilder().setCmd(command).build();
-    io.milvus.grpc.StringReply response;
+    Command request = Command.newBuilder().setCmd(command).build();
+    StringReply response;
 
     try {
       response = blockingStub.cmd(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Command `{0}`: {1}", command, response.getStringReply());
         return new Response(Response.Status.SUCCESS, response.getStringReply());
       } else {
@@ -715,14 +894,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.Status response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    Status response;
 
     try {
-      response = blockingStub.preloadTable(request);
+      response = blockingStub.preloadCollection(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Preloaded collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -744,22 +922,21 @@ public class MilvusGrpcClient implements MilvusClient {
       return new DescribeIndexResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.IndexParam response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    IndexParam response;
 
     try {
       response = blockingStub.describeIndex(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
         String extraParam = "";
-        for (io.milvus.grpc.KeyValuePair kv : response.getExtraParamsList()) {
+        for (KeyValuePair kv : response.getExtraParamsList()) {
           if (kv.getKey().contentEquals(extraParamKey)) {
             extraParam = kv.getValue();
           }
         }
         Index index =
-            new Index.Builder(response.getTableName(), IndexType.valueOf(response.getIndexType()))
+            new Index.Builder(response.getCollectionName(), IndexType.valueOf(response.getIndexType()))
                 .withParamsInJson(extraParam)
                 .build();
         logInfo(
@@ -789,14 +966,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.Status response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    Status response;
 
     try {
       response = blockingStub.dropIndex(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Dropped index for collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -819,22 +995,21 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.TableInfo response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    io.milvus.grpc.CollectionInfo response;
 
     try {
-      response = blockingStub.showTableInfo(request);
+      response = blockingStub.showCollectionInfo(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
 
         List<CollectionInfo.PartitionInfo> partitionInfos = new ArrayList<>();
 
-        for (io.milvus.grpc.PartitionStat partitionStat : response.getPartitionsStatList()) {
+        for (PartitionStat partitionStat : response.getPartitionsStatList()) {
 
           List<CollectionInfo.PartitionInfo.SegmentInfo> segmentInfos = new ArrayList<>();
 
-          for (io.milvus.grpc.SegmentStat segmentStat : partitionStat.getSegmentsStatList()) {
+          for (SegmentStat segmentStat : partitionStat.getSegmentsStatList()) {
 
             CollectionInfo.PartitionInfo.SegmentInfo segmentInfo =
                 new CollectionInfo.PartitionInfo.SegmentInfo(
@@ -882,14 +1057,14 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>(), null);
     }
 
-    io.milvus.grpc.VectorIdentity request =
-        io.milvus.grpc.VectorIdentity.newBuilder().setTableName(collectionName).setId(id).build();
-    io.milvus.grpc.VectorData response;
+    VectorIdentity request =
+        VectorIdentity.newBuilder().setCollectionName(collectionName).setId(id).build();
+    VectorData response;
 
     try {
       response = blockingStub.getVectorByID(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
 
         logInfo(
             "getVectorById for id={0} in collection `{1}` returned successfully!",
@@ -924,17 +1099,17 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
     }
 
-    io.milvus.grpc.GetVectorIDsParam request =
-        io.milvus.grpc.GetVectorIDsParam.newBuilder()
-            .setTableName(collectionName)
+    GetVectorIDsParam request =
+        GetVectorIDsParam.newBuilder()
+            .setCollectionName(collectionName)
             .setSegmentName(segmentName)
             .build();
-    io.milvus.grpc.VectorIds response;
+    VectorIds response;
 
     try {
       response = blockingStub.getVectorIDs(request);
 
-      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
 
         logInfo(
             "getVectorIds in collection `{0}`, segment `{1}` returned successfully!",
@@ -965,17 +1140,14 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.DeleteByIDParam request =
-        io.milvus.grpc.DeleteByIDParam.newBuilder()
-            .setTableName(collectionName)
-            .addAllIdArray(ids)
-            .build();
-    io.milvus.grpc.Status response;
+    DeleteByIDParam request =
+        DeleteByIDParam.newBuilder().setCollectionName(collectionName).addAllIdArray(ids).build();
+    Status response;
 
     try {
       response = blockingStub.deleteByID(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("deleteByIds in collection `{0}` completed successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -1008,14 +1180,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.FlushParam request =
-        io.milvus.grpc.FlushParam.newBuilder().addAllTableNameArray(collectionNames).build();
-    io.milvus.grpc.Status response;
+    FlushParam request = FlushParam.newBuilder().addAllCollectionNameArray(collectionNames).build();
+    Status response;
 
     try {
       response = blockingStub.flush(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Flushed collection {0} successfully!", collectionNames);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -1029,6 +1200,43 @@ public class MilvusGrpcClient implements MilvusClient {
     }
   }
 
+  @Override
+  public ListenableFuture<Response> flushAsync(@Nonnull List<String> collectionNames) {
+
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      return Futures.immediateFuture(new Response(Response.Status.CLIENT_NOT_CONNECTED));
+    }
+
+    FlushParam request = FlushParam.newBuilder().addAllCollectionNameArray(collectionNames).build();
+
+    ListenableFuture<Status> response;
+
+    response = futureStub.flush(request);
+
+    Futures.addCallback(
+        response,
+        new FutureCallback<Status>() {
+          @Override
+          public void onSuccess(Status result) {
+            if (result.getErrorCode() == ErrorCode.SUCCESS) {
+              logInfo("Flushed collection {0} successfully!", collectionNames);
+            } else {
+              logSevere("Flush collection {0} failed:\n{1}", collectionNames, result.toString());
+            }
+          }
+
+          @Override
+          public void onFailure(Throwable t) {
+            logSevere("FlushAsync failed:\n{0}", t.getMessage());
+          }
+        },
+        MoreExecutors.directExecutor());
+
+    return Futures.transform(
+        response, transformStatusToResponseFunc::apply, MoreExecutors.directExecutor());
+  }
+
   @Override
   public Response flush(String collectionName) {
     List<String> list =
@@ -1040,6 +1248,17 @@ public class MilvusGrpcClient implements MilvusClient {
     return flush(list);
   }
 
+  @Override
+  public ListenableFuture<Response> flushAsync(String collectionName) {
+    List<String> list =
+        new ArrayList<String>() {
+          {
+            add(collectionName);
+          }
+        };
+    return flushAsync(list);
+  }
+
   @Override
   public Response compact(String collectionName) {
     if (!channelIsReadyOrIdle()) {
@@ -1047,14 +1266,13 @@ public class MilvusGrpcClient implements MilvusClient {
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
-    io.milvus.grpc.Status response;
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+    Status response;
 
     try {
       response = blockingStub.compact(request);
 
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+      if (response.getErrorCode() == ErrorCode.SUCCESS) {
         logInfo("Compacted collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
@@ -1068,16 +1286,63 @@ public class MilvusGrpcClient implements MilvusClient {
     }
   }
 
+  @Override
+  public ListenableFuture<Response> compactAsync(@Nonnull String collectionName) {
+
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      return Futures.immediateFuture(new Response(Response.Status.CLIENT_NOT_CONNECTED));
+    }
+
+    CollectionName request = CollectionName.newBuilder().setCollectionName(collectionName).build();
+
+    ListenableFuture<Status> response;
+
+    response = futureStub.compact(request);
+
+    Futures.addCallback(
+        response,
+        new FutureCallback<Status>() {
+          @Override
+          public void onSuccess(Status result) {
+            if (result.getErrorCode() == ErrorCode.SUCCESS) {
+              logInfo("Compacted collection `{0}` successfully!", collectionName);
+            } else {
+              logSevere("Compact collection `{0}` failed:\n{1}", collectionName, result.toString());
+            }
+          }
+
+          @Override
+          public void onFailure(Throwable t) {
+            logSevere("CompactAsync failed:\n{0}", t.getMessage());
+          }
+        },
+        MoreExecutors.directExecutor());
+
+    return Futures.transform(
+        response, transformStatusToResponseFunc::apply, MoreExecutors.directExecutor());
+  }
+
   ///////////////////// Util Functions/////////////////////
-  private List<io.milvus.grpc.RowRecord> buildRowRecordList(
+  Function<Status, Response> transformStatusToResponseFunc =
+      status -> {
+        if (status.getErrorCode() == ErrorCode.SUCCESS) {
+          return new Response(Response.Status.SUCCESS);
+        } else {
+          return new Response(
+              Response.Status.valueOf(status.getErrorCodeValue()), status.getReason());
+        }
+      };
+
+  private List<RowRecord> buildRowRecordList(
       @Nonnull List<List<Float>> floatVectors, @Nonnull List<ByteBuffer> binaryVectors) {
-    List<io.milvus.grpc.RowRecord> rowRecordList = new ArrayList<>();
+    List<RowRecord> rowRecordList = new ArrayList<>();
 
     int largerSize = Math.max(floatVectors.size(), binaryVectors.size());
 
     for (int i = 0; i < largerSize; ++i) {
 
-      io.milvus.grpc.RowRecord.Builder rowRecordBuilder = io.milvus.grpc.RowRecord.newBuilder();
+      RowRecord.Builder rowRecordBuilder = RowRecord.newBuilder();
 
       if (i < floatVectors.size()) {
         rowRecordBuilder.addAllFloatData(floatVectors.get(i));
@@ -1093,7 +1358,7 @@ public class MilvusGrpcClient implements MilvusClient {
     return rowRecordList;
   }
 
-  private SearchResponse buildSearchResponse(io.milvus.grpc.TopKQueryResult topKQueryResult) {
+  private SearchResponse buildSearchResponse(TopKQueryResult topKQueryResult) {
 
     final int numQueries = (int) topKQueryResult.getRowNum();
     final int topK =

+ 7 - 3
src/main/java/io/milvus/client/SearchParam.java

@@ -136,11 +136,12 @@ public class SearchParam {
     }
 
     /**
-     * Optional. Default to empty <code>String</code>.
+     * Optional. Default to empty <code>String</code>. Search parameters are different for different
+     * index types. Refer to <a
+     * href="https://milvus.io/docs/v0.7.0/guides/milvus_operation.md">https://milvus.io/docs/v0.7.0/guides/milvus_operation.md</a>
+     * for more information.
      *
      * <pre>
-     *   For different index type, search parameter is different accordingly, for example:
-     *
      *   FLAT/IVFLAT/SQ8/IVFPQ: {"nprobe": 32}
      *   nprobe range:[1,999999]
      *
@@ -149,6 +150,9 @@ public class SearchParam {
      *
      *   HNSW: {"ef": 64}
      *   ef range:[topk, 4096]
+     *
+     *   ANNOY: {search_k", 0.05 * totalDataCount}
+     *   search_k range: none
      * </pre>
      *
      * @param paramsInJson extra parameters in JSON format

+ 74 - 65
src/main/proto/milvus.proto

@@ -17,27 +17,27 @@ message KeyValuePair {
 }
 
 /**
- * @brief Table name
+ * @brief Collection name
  */
-message TableName {
-    string table_name = 1;
+message CollectionName {
+    string collection_name = 1;
 }
 
 /**
- * @brief Table name list
+ * @brief Collection name list
  */
-message TableNameList {
+message CollectionNameList {
     Status status = 1;
-    repeated string table_names = 2;
+    repeated string collection_names = 2;
 }
 
 /**
- * @brief Table schema
+ * @brief Collection schema
  * metric_type: 1-L2, 2-IP
  */
-message TableSchema {
+message CollectionSchema {
     Status status = 1;
-    string table_name = 2;
+    string collection_name = 2;
     int64 dimension = 3;
     int64 index_file_size = 4;
     int32 metric_type = 5;
@@ -48,7 +48,7 @@ message TableSchema {
  * @brief Params of partition
  */
 message PartitionParam {
-    string table_name = 1;
+    string collection_name = 1;
     string tag = 2;
 }
 
@@ -72,7 +72,7 @@ message RowRecord {
  * @brief Params to be inserted
  */
 message InsertParam {
-    string table_name = 1;
+    string collection_name = 1;
     repeated RowRecord row_record_array = 2;
     repeated int64 row_id_array = 3;            //optional
     string partition_tag = 4;
@@ -91,7 +91,7 @@ message VectorIds {
  * @brief Params for searching vector
  */
 message SearchParam {
-    string table_name = 1;
+    string collection_name = 1;
     repeated string partition_tag_array = 2;
     repeated RowRecord query_record_array = 3;
     int64 topk = 4;
@@ -110,7 +110,7 @@ message SearchInFilesParam {
  * @brief Params for searching vector by ID
  */
 message SearchByIDParam {
-    string table_name = 1;
+    string collection_name = 1;
     repeated string partition_tag_array = 2;
     int64 id = 3;
     int64 topk = 4;
@@ -144,11 +144,11 @@ message BoolReply {
 }
 
 /**
- * @brief Return table row count
+ * @brief Return collection row count
  */
-message TableRowCount {
+message CollectionRowCount {
     Status status = 1;
-    int64 table_row_count = 2;
+    int64 collection_row_count = 2;
 }
 
 /**
@@ -164,7 +164,7 @@ message Command {
  */
 message IndexParam {
     Status status = 1;
-    string table_name = 2;
+    string collection_name = 2;
     int32 index_type = 3;
     repeated KeyValuePair extra_params = 4;
 }
@@ -173,14 +173,14 @@ message IndexParam {
  * @brief Flush params
  */
 message FlushParam {
-    repeated string table_name_array = 1;
+    repeated string collection_name_array = 1;
 }
 
 /**
  * @brief Flush params
  */
 message DeleteByIDParam {
-    string table_name = 1;
+    string collection_name = 1;
     repeated int64 id_array = 2;
 }
 
@@ -195,7 +195,7 @@ message SegmentStat {
 }
 
 /**
- * @brief table statistics
+ * @brief collection statistics
  */
 message PartitionStat {
     string tag = 1;
@@ -204,9 +204,9 @@ message PartitionStat {
 }
 
 /**
- * @brief table information
+ * @brief collection information
  */
-message TableInfo {
+message CollectionInfo {
     Status status = 1;
     int64 total_row_count = 2;
     repeated PartitionStat partitions_stat = 3;
@@ -216,7 +216,7 @@ message TableInfo {
  * @brief vector identity
  */
 message VectorIdentity {
-    string table_name = 1;
+    string collection_name = 1;
     int64 id = 2;
 }
 
@@ -232,76 +232,76 @@ message VectorData {
  * @brief get vector ids from a segment parameters
  */
 message GetVectorIDsParam {
-    string table_name = 1;
+    string collection_name = 1;
     string segment_name = 2;
 }
 
 service MilvusService {
     /**
-     * @brief This method is used to create table
+     * @brief This method is used to create collection
      *
-     * @param TableSchema, use to provide table information to be created.
+     * @param CollectionSchema, use to provide collection information to be created.
      *
      * @return Status
      */
-    rpc CreateTable(TableSchema) returns (Status){}
+    rpc CreateCollection(CollectionSchema) returns (Status){}
 
     /**
-     * @brief This method is used to test table existence.
+     * @brief This method is used to test collection existence.
      *
-     * @param TableName, table name is going to be tested.
+     * @param CollectionName, collection name is going to be tested.
      *
      * @return BoolReply
      */
-    rpc HasTable(TableName) returns (BoolReply) {}
+    rpc HasCollection(CollectionName) returns (BoolReply) {}
 
     /**
-     * @brief This method is used to get table schema.
+     * @brief This method is used to get collection schema.
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
-     * @return TableSchema
+     * @return CollectionSchema
      */
-    rpc DescribeTable(TableName) returns (TableSchema) {}
+    rpc DescribeCollection(CollectionName) returns (CollectionSchema) {}
 
     /**
-     * @brief This method is used to get table schema.
+     * @brief This method is used to get collection schema.
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
-     * @return TableRowCount
+     * @return CollectionRowCount
      */
-    rpc CountTable(TableName) returns (TableRowCount) {}
+    rpc CountCollection(CollectionName) returns (CollectionRowCount) {}
 
     /**
-     * @brief This method is used to list all tables.
+     * @brief This method is used to list all collections.
      *
      * @param Command, dummy parameter.
      *
-     * @return TableNameList
+     * @return CollectionNameList
      */
-    rpc ShowTables(Command) returns (TableNameList) {}
+    rpc ShowCollections(Command) returns (CollectionNameList) {}
 
     /**
-     * @brief This method is used to get table detail information.
+     * @brief This method is used to get collection detail information.
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
-     * @return TableInfo
+     * @return CollectionInfo
      */
-    rpc ShowTableInfo(TableName) returns (TableInfo) {}
+    rpc ShowCollectionInfo(CollectionName) returns (CollectionInfo) {}
 
     /**
-     * @brief This method is used to delete table.
+     * @brief This method is used to delete collection.
      *
-     * @param TableName, table name is going to be deleted.
+     * @param CollectionName, collection name is going to be deleted.
      *
-     * @return TableNameList
+     * @return CollectionNameList
      */
-    rpc DropTable(TableName) returns (Status) {}
+    rpc DropCollection(CollectionName) returns (Status) {}
 
     /**
-     * @brief This method is used to build index by table in sync mode.
+     * @brief This method is used to build index by collection in sync mode.
      *
      * @param IndexParam, index paramters.
      *
@@ -312,20 +312,20 @@ service MilvusService {
     /**
      * @brief This method is used to describe index
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
      * @return IndexParam
      */
-    rpc DescribeIndex(TableName) returns (IndexParam) {}
+    rpc DescribeIndex(CollectionName) returns (IndexParam) {}
 
     /**
      * @brief This method is used to drop index
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
      * @return Status
      */
-    rpc DropIndex(TableName) returns (Status) {}
+    rpc DropIndex(CollectionName) returns (Status) {}
 
     /**
      * @brief This method is used to create partition
@@ -339,11 +339,11 @@ service MilvusService {
     /**
      * @brief This method is used to show partition information
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
      * @return PartitionList
      */
-    rpc ShowPartitions(TableName) returns (PartitionList) {}
+    rpc ShowPartitions(CollectionName) returns (PartitionList) {}
 
     /**
      * @brief This method is used to drop partition
@@ -355,7 +355,7 @@ service MilvusService {
     rpc DropPartition(PartitionParam) returns (Status) {}
 
     /**
-     * @brief This method is used to add vector array to table.
+     * @brief This method is used to add vector array to collection.
      *
      * @param InsertParam, insert parameters.
      *
@@ -375,14 +375,14 @@ service MilvusService {
     /**
      * @brief This method is used to get vector ids from a segment
      *
-     * @param GetVectorIDsParam, target table and segment
+     * @param GetVectorIDsParam, target collection and segment
      *
      * @return VectorIds
      */
     rpc GetVectorIDs(GetVectorIDsParam) returns (VectorIds) {}
 
     /**
-     * @brief This method is used to query vector in table.
+     * @brief This method is used to query vector in collection.
      *
      * @param SearchParam, search parameters.
      *
@@ -390,6 +390,15 @@ service MilvusService {
      */
     rpc Search(SearchParam) returns (TopKQueryResult) {}
 
+    /**
+     * @brief This method is used to query vector by id.
+     *
+     * @param SearchByIDParam, search parameters.
+     *
+     * @return TopKQueryResult
+     */
+    rpc SearchByID(SearchByIDParam) returns (TopKQueryResult) {}
+
     /**
      * @brief This method is used to query vector in specified files.
      *
@@ -418,13 +427,13 @@ service MilvusService {
     rpc DeleteByID(DeleteByIDParam) returns (Status) {}
 
     /**
-     * @brief This method is used to preload table
+     * @brief This method is used to preload collection
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
      * @return Status
      */
-    rpc PreloadTable(TableName) returns (Status) {}
+    rpc PreloadCollection(CollectionName) returns (Status) {}
 
     /**
      * @brief This method is used to flush buffer into storage.
@@ -436,11 +445,11 @@ service MilvusService {
     rpc Flush(FlushParam) returns (Status) {}
 
     /**
-     * @brief This method is used to compact table
+     * @brief This method is used to compact collection
      *
-     * @param TableName, target table name.
+     * @param CollectionName, target collection name.
      *
      * @return Status
      */
-    rpc Compact(TableName) returns (Status) {}
+    rpc Compact(CollectionName) returns (Status) {}
 }

+ 2 - 2
src/main/proto/status.proto

@@ -11,11 +11,11 @@ enum ErrorCode {
     UNEXPECTED_ERROR = 1;
     CONNECT_FAILED = 2;
     PERMISSION_DENIED = 3;
-    TABLE_NOT_EXISTS = 4;
+    COLLECTION_NOT_EXISTS = 4;
     ILLEGAL_ARGUMENT = 5;
     ILLEGAL_DIMENSION = 7;
     ILLEGAL_INDEX_TYPE = 8;
-    ILLEGAL_TABLE_NAME = 9;
+    ILLEGAL_COLLECTION_NAME = 9;
     ILLEGAL_TOPK = 10;
     ILLEGAL_ROWRECORD = 11;
     ILLEGAL_VECTOR_ID = 12;

+ 121 - 0
src/test/java/io/milvus/client/MilvusGrpcClientTest.java

@@ -19,10 +19,12 @@
 
 package io.milvus.client;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.commons.text.RandomStringGenerator;
 
 import java.nio.ByteBuffer;
 import java.util.*;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.DoubleStream;
@@ -287,6 +289,21 @@ class MilvusClientTest {
     assertTrue(createIndexResponse.ok());
   }
 
+  @org.junit.jupiter.api.Test
+  void createIndexAsync() throws ExecutionException, InterruptedException {
+    insert();
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    Index index =
+        new Index.Builder(randomCollectionName, IndexType.IVF_SQ8)
+            .withParamsInJson("{\"nlist\": 19384}")
+            .build();
+
+    ListenableFuture<Response> createIndexResponseFuture = client.createIndexAsync(index);
+    Response createIndexResponse = createIndexResponseFuture.get();
+    assertTrue(createIndexResponse.ok());
+  }
+
   @org.junit.jupiter.api.Test
   void insert() {
     List<List<Float>> vectors = generateFloatVectors(size, dimension);
@@ -297,6 +314,17 @@ class MilvusClientTest {
     assertEquals(size, insertResponse.getVectorIds().size());
   }
 
+  @org.junit.jupiter.api.Test
+  void insertAsync() throws ExecutionException, InterruptedException {
+    List<List<Float>> vectors = generateFloatVectors(size, dimension);
+    InsertParam insertParam =
+        new InsertParam.Builder(randomCollectionName).withFloatVectors(vectors).build();
+    ListenableFuture<InsertResponse> insertResponseFuture = client.insertAsync(insertParam);
+    InsertResponse insertResponse = insertResponseFuture.get();
+    assertTrue(insertResponse.ok());
+    assertEquals(size, insertResponse.getVectorIds().size());
+  }
+
   @org.junit.jupiter.api.Test
   void insertBinary() {
     final long binaryDimension = 10000;
@@ -361,6 +389,48 @@ class MilvusClientTest {
     }
   }
 
+  @org.junit.jupiter.api.Test
+  void searchAsync() throws ExecutionException, InterruptedException {
+    List<List<Float>> vectors = generateFloatVectors(size, dimension);
+    vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
+    InsertParam insertParam =
+        new InsertParam.Builder(randomCollectionName).withFloatVectors(vectors).build();
+    InsertResponse insertResponse = client.insert(insertParam);
+    assertTrue(insertResponse.ok());
+    List<Long> vectorIds = insertResponse.getVectorIds();
+    assertEquals(size, vectorIds.size());
+
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    final int searchSize = 5;
+    List<List<Float>> vectorsToSearch = vectors.subList(0, searchSize);
+
+    final long topK = 10;
+    SearchParam searchParam =
+        new SearchParam.Builder(randomCollectionName)
+            .withFloatVectors(vectorsToSearch)
+            .withTopK(topK)
+            .withParamsInJson("{\"nprobe\": 20}")
+            .build();
+    ListenableFuture<SearchResponse> searchResponseFuture = client.searchAsync(searchParam);
+    SearchResponse searchResponse = searchResponseFuture.get();
+    assertTrue(searchResponse.ok());
+    List<List<Long>> resultIdsList = searchResponse.getResultIdsList();
+    assertEquals(searchSize, resultIdsList.size());
+    List<List<Float>> resultDistancesList = searchResponse.getResultDistancesList();
+    assertEquals(searchSize, resultDistancesList.size());
+    List<List<SearchResponse.QueryResult>> queryResultsList = searchResponse.getQueryResultsList();
+    assertEquals(searchSize, queryResultsList.size());
+    final double epsilon = 0.001;
+    for (int i = 0; i < searchSize; i++) {
+      SearchResponse.QueryResult firstQueryResult = queryResultsList.get(i).get(0);
+      assertEquals(vectorIds.get(i), firstQueryResult.getVectorId());
+      assertEquals(vectorIds.get(i), resultIdsList.get(i).get(0));
+      assertTrue(Math.abs(1 - firstQueryResult.getDistance()) < epsilon);
+      assertTrue(Math.abs(1 - resultDistancesList.get(i).get(0)) < epsilon);
+    }
+  }
+
   @org.junit.jupiter.api.Test
   void searchBinary() {
     final long binaryDimension = 10000;
@@ -597,6 +667,11 @@ class MilvusClientTest {
     assertTrue(client.flush(randomCollectionName).ok());
   }
 
+  @org.junit.jupiter.api.Test
+  void flushAsync() throws ExecutionException, InterruptedException {
+    assertTrue(client.flushAsync(randomCollectionName).get().ok());
+  }
+
   @org.junit.jupiter.api.Test
   void compact() {
     List<List<Float>> vectors = generateFloatVectors(size, dimension);
@@ -642,4 +717,50 @@ class MilvusClientTest {
 
     assertTrue(currentSegmentSize < previousSegmentSize);
   }
+
+  @org.junit.jupiter.api.Test
+  void compactAsync() throws ExecutionException, InterruptedException {
+    List<List<Float>> vectors = generateFloatVectors(size, dimension);
+    InsertParam insertParam =
+        new InsertParam.Builder(randomCollectionName).withFloatVectors(vectors).build();
+    InsertResponse insertResponse = client.insert(insertParam);
+    assertTrue(insertResponse.ok());
+    List<Long> vectorIds = insertResponse.getVectorIds();
+    assertEquals(size, vectorIds.size());
+
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    ShowCollectionInfoResponse showCollectionInfoResponse =
+        client.showCollectionInfo(randomCollectionName);
+    assertTrue(showCollectionInfoResponse.getCollectionInfo().isPresent());
+    CollectionInfo.PartitionInfo.SegmentInfo segmentInfo =
+        showCollectionInfoResponse
+            .getCollectionInfo()
+            .get()
+            .getPartitionInfos()
+            .get(0)
+            .getSegmentInfos()
+            .get(0);
+    long previousSegmentSize = segmentInfo.getDataSize();
+
+    assertTrue(client.deleteByIds(randomCollectionName, vectorIds.subList(0, 100)).ok());
+
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    assertTrue(client.compactAsync(randomCollectionName).get().ok());
+
+    showCollectionInfoResponse = client.showCollectionInfo(randomCollectionName);
+    assertTrue(showCollectionInfoResponse.getCollectionInfo().isPresent());
+    segmentInfo =
+        showCollectionInfoResponse
+            .getCollectionInfo()
+            .get()
+            .getPartitionInfos()
+            .get(0)
+            .getSegmentInfos()
+            .get(0);
+    long currentSegmentSize = segmentInfo.getDataSize();
+
+    assertTrue(currentSegmentSize < previousSegmentSize);
+  }
 }