Selaa lähdekoodia

Release 0.5.0 (#85)

* fix partition in search not working and add unittest

* update CHANGELOG and version

* update

* update

* update

* 0.5.0

* add log option

Signed-off-by: Zhiru Zhu <zhiru.zhu@zilliz.com>

* update source code

Signed-off-by: youny626 <zzhu@fandm.edu>

* update unit test

Signed-off-by: youny626 <zzhu@fandm.edu>

* update

Signed-off-by: Zhiru Zhu <zzhu@fandm.edu>

* update

Signed-off-by: youny626 <zzhu@fandm.edu>

* update examples

Signed-off-by: youny626 <zzhu@fandm.edu>

* update

Signed-off-by: Zhiru Zhu <zzhu@fandm.edu>

* update

Signed-off-by: Zhiru Zhu <zzhu@fandm.edu>

* update

Signed-off-by: Zhiru Zhu <zzhu@fandm.edu>

* update

Signed-off-by: Zhiru Zhu <zzhu@fandm.edu>

* update

Signed-off-by: Zhiru Zhu <zzhu@fandm.edu>
Zhiru Zhu 5 vuotta sitten
vanhempi
commit
0ab38decf6
35 muutettua tiedostoa jossa 1743 lisäystä ja 1367 poistoa
  1. 2 0
      CHANGELOG.md
  2. 2 0
      examples/milvus-sdk-java-examples.iml
  3. 7 2
      examples/pom.xml
  4. 79 48
      examples/src/main/java/MilvusClientExample.java
  5. 2 0
      milvus-sdk-java.iml
  6. 10 16
      pom.xml
  7. 78 0
      src/main/java/io/milvus/client/CollectionInfo.java
  8. 16 16
      src/main/java/io/milvus/client/CollectionMapping.java
  9. 5 28
      src/main/java/io/milvus/client/ConnectParam.java
  10. 0 77
      src/main/java/io/milvus/client/CreateIndexParam.java
  11. 0 56
      src/main/java/io/milvus/client/DateRange.java
  12. 14 11
      src/main/java/io/milvus/client/DescribeCollectionResponse.java
  13. 1 0
      src/main/java/io/milvus/client/DescribeIndexResponse.java
  14. 12 8
      src/main/java/io/milvus/client/GetCollectionRowCountResponse.java
  15. 59 0
      src/main/java/io/milvus/client/GetVectorByIdResponse.java
  16. 30 0
      src/main/java/io/milvus/client/GetVectorIdsResponse.java
  17. 10 9
      src/main/java/io/milvus/client/HasCollectionResponse.java
  18. 51 16
      src/main/java/io/milvus/client/Index.java
  19. 7 4
      src/main/java/io/milvus/client/IndexType.java
  20. 46 16
      src/main/java/io/milvus/client/InsertParam.java
  21. 1 0
      src/main/java/io/milvus/client/InsertResponse.java
  22. 9 2
      src/main/java/io/milvus/client/MetricType.java
  23. 159 91
      src/main/java/io/milvus/client/MilvusClient.java
  24. 445 238
      src/main/java/io/milvus/client/MilvusGrpcClient.java
  25. 0 80
      src/main/java/io/milvus/client/Partition.java
  26. 0 1
      src/main/java/io/milvus/client/Response.java
  27. 0 62
      src/main/java/io/milvus/client/SearchInFilesParam.java
  28. 76 55
      src/main/java/io/milvus/client/SearchParam.java
  29. 1 0
      src/main/java/io/milvus/client/SearchResponse.java
  30. 36 0
      src/main/java/io/milvus/client/ShowCollectionInfoResponse.java
  31. 11 8
      src/main/java/io/milvus/client/ShowCollectionsResponse.java
  32. 7 41
      src/main/java/io/milvus/client/ShowPartitionsResponse.java
  33. 219 387
      src/main/proto/milvus.proto
  34. 0 1
      src/main/proto/status.proto
  35. 348 94
      src/test/java/io/milvus/client/MilvusGrpcClientTest.java

+ 2 - 0
CHANGELOG.md

@@ -1,5 +1,7 @@
 # Changelog     
 
+## milvus-sdk-java 0.5.0 (2020-03-11)
+
 ## milvus-sdk-java 0.4.1 (2019-12-16)
 
 ### Bug

+ 2 - 0
examples/milvus-sdk-java-examples.iml

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4" />

+ 7 - 2
examples/pom.xml

@@ -25,7 +25,7 @@
 
     <groupId>io.milvus</groupId>
     <artifactId>milvus-sdk-java-examples</artifactId>
-    <version>0.3.0</version>
+    <version>0.5.0</version>
     <build>
         <plugins>
             <plugin>
@@ -63,7 +63,12 @@
         <dependency>
             <groupId>io.milvus</groupId>
             <artifactId>milvus-sdk-java</artifactId>
-            <version>0.4.1</version>
+            <version>0.5.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>2.8.6</version>
         </dependency>
     </dependencies>
 

+ 79 - 48
examples/src/main/java/MilvusClientExample.java

@@ -17,24 +17,29 @@
  * under the License.
  */
 
+import com.google.gson.JsonObject;
 import io.milvus.client.*;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.SplittableRandom;
-import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
 import java.util.stream.Collectors;
 import java.util.stream.DoubleStream;
 
+// This is a simple example demonstrating how to use the Milvus Java SDK.
+// For detailed API document, please refer to
+// https://milvus-io.github.io/milvus-sdk-java/javadoc/io/milvus/client/package-summary.html
+// You can also find more information in https://milvus.io/
 public class MilvusClientExample {
 
   // Helper function that generates random vectors
   static List<List<Float>> generateVectors(long vectorCount, long dimension) {
-    SplittableRandom splittableRandom = new SplittableRandom();
+    SplittableRandom splitcollectionRandom = new SplittableRandom();
     List<List<Float>> vectors = new ArrayList<>();
-    for (int i = 0; i < vectorCount; ++i) {
-      splittableRandom = splittableRandom.split();
-      DoubleStream doubleStream = splittableRandom.doubles(dimension);
+    for (long i = 0; i < vectorCount; ++i) {
+      splitcollectionRandom = splitcollectionRandom.split();
+      DoubleStream doubleStream = splitcollectionRandom.doubles(dimension);
       List<Float> vector =
           doubleStream.boxed().map(Double::floatValue).collect(Collectors.toList());
       vectors.add(vector);
@@ -55,94 +60,102 @@ public class MilvusClientExample {
 
     // You may need to change the following to the host and port of your Milvus server
     final String host = "localhost";
-    final String port = "19530";
+    final int port = 19530;
 
     // Create Milvus client
-    MilvusClient client = new MilvusGrpcClient();
+    // You can specify the log level. Currently we have three levels of logs: INFO, WARNING and
+    // SEVERE
+    MilvusClient client = new MilvusGrpcClient(Level.ALL);
 
     // Connect to Milvus server
     ConnectParam connectParam = new ConnectParam.Builder().withHost(host).withPort(port).build();
     try {
       Response connectResponse = client.connect(connectParam);
     } catch (ConnectFailedException e) {
-      System.out.println(e.toString());
+      System.out.println("Failed to connect to Milvus server: " + e.toString());
       throw e;
     }
 
     // Check whether we are connected
     boolean connected = client.isConnected();
-    System.out.println("Connected = " + connected);
 
-    // Create a table with the following table schema
-    final String tableName = "example"; // table name
+    // Create a collection with the following collection mapping
+    final String collectionName = "example"; // collection name
     final long dimension = 128; // dimension of each vector
     final long indexFileSize = 1024; // maximum size (in MB) of each index file
     final MetricType metricType = MetricType.IP; // we choose IP (Inner Product) as our metric type
-    TableSchema tableSchema =
-        new TableSchema.Builder(tableName, dimension)
+    CollectionMapping collectionMapping =
+        new CollectionMapping.Builder(collectionName, dimension)
             .withIndexFileSize(indexFileSize)
             .withMetricType(metricType)
             .build();
-    Response createTableResponse = client.createTable(tableSchema);
-    System.out.println(createTableResponse);
+    Response createCollectionResponse = client.createCollection(collectionMapping);
 
-    // Check whether the table exists
-    HasTableResponse hasTableResponse = client.hasTable(tableName);
-    System.out.println(hasTableResponse);
+    // Check whether the collection exists
+    HasCollectionResponse hasCollectionResponse = client.hasCollection(collectionName);
 
-    // Describe the table
-    DescribeTableResponse describeTableResponse = client.describeTable(tableName);
-    System.out.println(describeTableResponse);
+    // Describe the collection
+    DescribeCollectionResponse describeCollectionResponse =
+        client.describeCollection(collectionName);
 
-    // Insert randomly generated vectors to table
+    // Insert randomly generated vectors to collection
     final int vectorCount = 100000;
     List<List<Float>> vectors = generateVectors(vectorCount, dimension);
     vectors =
         vectors.stream().map(MilvusClientExample::normalizeVector).collect(Collectors.toList());
-    InsertParam insertParam = new InsertParam.Builder(tableName, vectors).build();
+    InsertParam insertParam =
+        new InsertParam.Builder(collectionName).withFloatVectors(vectors).build();
     InsertResponse insertResponse = client.insert(insertParam);
-    System.out.println(insertResponse);
     // Insert returns a list of vector ids that you will be using (if you did not supply them
     // yourself) to reference the vectors you just inserted
     List<Long> vectorIds = insertResponse.getVectorIds();
 
-    // The data we just inserted won't be serialized and written to meta until the next second
-    // wait 1 second here
-    TimeUnit.SECONDS.sleep(1);
+    // Flush data in collection
+    Response flushResponse = client.flush(collectionName);
 
-    // Get current row count of table
-    GetTableRowCountResponse getTableRowCountResponse = client.getTableRowCount(tableName);
-    System.out.println(getTableRowCountResponse);
+    // Get current row count of collection
+    GetCollectionRowCountResponse getCollectionRowCountResponse =
+        client.getCollectionRowCount(collectionName);
 
-    // Create index for the table
+    // Create index for the collection
     // We choose IVF_SQ8 as our index type here. Refer to IndexType javadoc for a
     // complete explanation of different index types
     final IndexType indexType = IndexType.IVF_SQ8;
-    Index index = new Index.Builder().withIndexType(indexType).build();
-    CreateIndexParam createIndexParam =
-        new CreateIndexParam.Builder(tableName).withIndex(index).build();
-    Response createIndexResponse = client.createIndex(createIndexParam);
-    System.out.println(createIndexResponse);
+    // Each index type has its optional parameters you can set. Refer to the Milvus documentation
+    // for how to set the optimal parameters based on your needs.
+    JsonObject indexParamsJson = new JsonObject();
+    indexParamsJson.addProperty("nlist", 16384);
+    Index index =
+        new Index.Builder(collectionName, indexType)
+            .withParamsInJson(indexParamsJson.toString())
+            .build();
+    Response createIndexResponse = client.createIndex(index);
 
-    // Describe the index for your table
-    DescribeIndexResponse describeIndexResponse = client.describeIndex(tableName);
-    System.out.println(describeIndexResponse);
+    // Describe the index for your collection
+    DescribeIndexResponse describeIndexResponse = client.describeIndex(collectionName);
 
     // Search vectors
     // Searching the first 5 vectors of the vectors we just inserted
     final int searchBatchSize = 5;
     List<List<Float>> vectorsToSearch = vectors.subList(0, searchBatchSize);
     final long topK = 10;
+    // Based on the index you created, the available search parameters will be different. Refer to
+    // the Milvus documentation for how to set the optimal parameters based on your needs.
+    JsonObject searchParamsJson = new JsonObject();
+    searchParamsJson.addProperty("nprobe", 20);
     SearchParam searchParam =
-        new SearchParam.Builder(tableName, vectorsToSearch).withTopK(topK).build();
+        new SearchParam.Builder(collectionName)
+            .withFloatVectors(vectorsToSearch)
+            .withTopK(topK)
+            .withParamsInJson(searchParamsJson.toString())
+            .build();
     SearchResponse searchResponse = client.search(searchParam);
-    System.out.println(searchResponse);
     if (searchResponse.ok()) {
       List<List<SearchResponse.QueryResult>> queryResultsList =
           searchResponse.getQueryResultsList();
       final double epsilon = 0.001;
       for (int i = 0; i < searchBatchSize; i++) {
-        // Since we are searching for vector that is already present in the table,
+        // Since we are searching for vector that is already present in the collection,
         // the first result vector should be itself and the distance (inner product) should be
         // very close to 1 (some precision is lost during the process)
         SearchResponse.QueryResult firstQueryResult = queryResultsList.get(i).get(0);
@@ -153,13 +166,31 @@ public class MilvusClientExample {
       }
     }
 
-    // Drop index for the table
-    Response dropIndexResponse = client.dropIndex(tableName);
-    System.out.println(dropIndexResponse);
+    // Delete the first 5 of vectors you just searched
+    Response deleteByIdsResponse =
+        client.deleteByIds(collectionName, vectorIds.subList(0, searchBatchSize));
+
+    // Flush again, so deletions to data become visible
+    flushResponse = client.flush(collectionName);
+
+    // Try to get the corresponding vector of the first id you just deleted.
+    GetVectorByIdResponse getVectorByIdResponse =
+        client.getVectorById(collectionName, vectorIds.get(0));
+    // Obviously you won't get anything
+    if (getVectorByIdResponse.exists()) {
+      throw new AssertionError("This can never happen!");
+    }
+
+    // Compact 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.
+    Response compactResponse = client.compact(collectionName);
+
+    // Drop index for the collection
+    Response dropIndexResponse = client.dropIndex(collectionName);
 
-    // Drop table
-    Response dropTableResponse = client.dropTable(tableName);
-    System.out.println(dropTableResponse);
+    // Drop collection
+    Response dropCollectionResponse = client.dropCollection(collectionName);
 
     // Disconnect from Milvus server
     try {

+ 2 - 0
milvus-sdk-java.iml

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4" />

+ 10 - 16
pom.xml

@@ -25,7 +25,7 @@
 
     <groupId>io.milvus</groupId>
     <artifactId>milvus-sdk-java</artifactId>
-    <version>0.4.1</version>
+    <version>0.5.0</version>
     <packaging>jar</packaging>
 
     <name>io.milvus:milvus-sdk-java</name>
@@ -64,9 +64,9 @@
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <grpc.version>1.24.0</grpc.version>
-        <protobuf.version>3.10.0</protobuf.version>
-        <protoc.version>3.10.0</protoc.version>
+        <grpc.version>1.27.2</grpc.version>
+        <protobuf.version>3.11.0</protobuf.version>
+        <protoc.version>3.11.0</protoc.version>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
     </properties>
@@ -89,11 +89,6 @@
             <artifactId>maven-gpg-plugin</artifactId>
             <version>1.6</version>
         </dependency>
-        <dependency>
-            <groupId>com.google.googlejavaformat</groupId>
-            <artifactId>google-java-format</artifactId>
-            <version>1.7</version>
-        </dependency>
         <dependency>
             <groupId>io.grpc</groupId>
             <artifactId>grpc-netty-shaded</artifactId>
@@ -123,6 +118,11 @@
             <artifactId>protobuf-java-util</artifactId>
             <version>${protobuf.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.google.errorprone</groupId>
+            <artifactId>error_prone_annotations</artifactId>
+            <version>2.3.4</version> <!-- prefer to use 2.3.3 or later -->
+        </dependency>
         <dependency>
             <groupId>org.junit.jupiter</groupId>
             <artifactId>junit-jupiter</artifactId>
@@ -254,13 +254,7 @@
                         <id>enforce</id>
                         <configuration>
                             <rules>
-                                <requireUpperBoundDeps>
-                                    <excludes>
-                                        <exclude>com.google.guava:guava</exclude>
-                                        <exclude>com.google.errorprone:error_prone_annotations</exclude>
-                                        <exclude>com.google.protobuf:protobuf-java</exclude>
-                                    </excludes>
-                                </requireUpperBoundDeps>
+                                <requireUpperBoundDeps/>
                             </rules>
                         </configuration>
                         <goals>

+ 78 - 0
src/main/java/io/milvus/client/CollectionInfo.java

@@ -0,0 +1,78 @@
+package io.milvus.client;
+
+import java.util.List;
+
+/** Represents information about a collection */
+public class CollectionInfo {
+  private final long rowCount;
+  private final List<PartitionInfo> partitionInfos;
+
+  CollectionInfo(long rowCount, List<PartitionInfo> partitionInfos) {
+    this.rowCount = rowCount;
+    this.partitionInfos = partitionInfos;
+  }
+
+  public long getRowCount() {
+    return rowCount;
+  }
+
+  public List<PartitionInfo> getPartitionInfos() {
+    return partitionInfos;
+  }
+
+  /** Represents information about a single partition in a collection */
+  public static class PartitionInfo {
+    private final String tag;
+    private final long rowCount;
+    private final List<SegmentInfo> segmentInfos;
+
+    PartitionInfo(String tag, long rowCount, List<SegmentInfo> segmentInfos) {
+      this.tag = tag;
+      this.rowCount = rowCount;
+      this.segmentInfos = segmentInfos;
+    }
+
+    public String getTag() {
+      return tag;
+    }
+
+    public long getRowCount() {
+      return rowCount;
+    }
+
+    public List<SegmentInfo> getSegmentInfos() {
+      return segmentInfos;
+    }
+
+    /** Represents information about a single segment in a partition */
+    public static class SegmentInfo {
+      private final String segmentName;
+      private final long rowCount;
+      private final String indexName;
+      private final long dataSize;
+
+      SegmentInfo(String segmentName, long rowCount, String indexName, long dataSize) {
+        this.segmentName = segmentName;
+        this.rowCount = rowCount;
+        this.indexName = indexName;
+        this.dataSize = dataSize;
+      }
+
+      public String getSegmentName() {
+        return segmentName;
+      }
+
+      public long getRowCount() {
+        return rowCount;
+      }
+
+      public String getIndexName() {
+        return indexName;
+      }
+
+      public long getDataSize() {
+        return dataSize;
+      }
+    }
+  }
+}

+ 16 - 16
src/main/java/io/milvus/client/TableSchema.java → src/main/java/io/milvus/client/CollectionMapping.java

@@ -21,23 +21,23 @@ package io.milvus.client;
 
 import javax.annotation.Nonnull;
 
-/** Represents a table schema */
+/** Represents a collection mapping */
 // Builder Pattern
-public class TableSchema {
-  private final String tableName;
+public class CollectionMapping {
+  private final String collectionName;
   private final long dimension;
   private final long indexFileSize;
   private final MetricType metricType;
 
-  private TableSchema(@Nonnull Builder builder) {
-    tableName = builder.tableName;
+  private CollectionMapping(@Nonnull Builder builder) {
+    collectionName = builder.collectionName;
     dimension = builder.dimension;
     indexFileSize = builder.indexFileSize;
     metricType = builder.metricType;
   }
 
-  public String getTableName() {
-    return tableName;
+  public String getCollectionName() {
+    return collectionName;
   }
 
   public long getDimension() {
@@ -55,14 +55,14 @@ public class TableSchema {
   @Override
   public String toString() {
     return String.format(
-        "TableSchema = {tableName = %s, dimension = %d, indexFileSize = %d, metricType = %s}",
-        tableName, dimension, indexFileSize, metricType.name());
+        "CollectionMapping = {collectionName = %s, dimension = %d, indexFileSize = %d, metricType = %s}",
+        collectionName, dimension, indexFileSize, metricType.name());
   }
 
-  /** Builder for <code>TableSchema</code> */
+  /** Builder for <code>CollectionMapping</code> */
   public static class Builder {
     // Required parameters
-    private final String tableName;
+    private final String collectionName;
     private final long dimension;
 
     // Optional parameters - initialized to default values
@@ -70,11 +70,11 @@ public class TableSchema {
     private MetricType metricType = MetricType.L2;
 
     /**
-     * @param tableName table name
+     * @param collectionName collection name
      * @param dimension vector dimension
      */
-    public Builder(@Nonnull String tableName, long dimension) {
-      this.tableName = tableName;
+    public Builder(@Nonnull String collectionName, long dimension) {
+      this.collectionName = collectionName;
       this.dimension = dimension;
     }
 
@@ -101,8 +101,8 @@ public class TableSchema {
       return this;
     }
 
-    public TableSchema build() {
-      return new TableSchema(this);
+    public CollectionMapping build() {
+      return new CollectionMapping(this);
     }
   }
 }

+ 5 - 28
src/main/java/io/milvus/client/ConnectParam.java

@@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit;
 /** Contains parameters for connecting to Milvus server */
 public class ConnectParam {
   private final String host;
-  private final String port;
+  private final int port;
   private final long connectTimeoutNanos;
   private final long keepAliveTimeNanos;
   private final long keepAliveTimeoutNanos;
@@ -46,7 +46,7 @@ public class ConnectParam {
     return host;
   }
 
-  public String getPort() {
+  public int getPort() {
     return port;
   }
 
@@ -70,33 +70,11 @@ public class ConnectParam {
     return timeUnit.convert(idleTimeoutNanos, TimeUnit.NANOSECONDS);
   }
 
-  @Override
-  public String toString() {
-    return "ConnectParam {"
-        + "host='"
-        + host
-        + '\''
-        + ", port='"
-        + port
-        + '\''
-        + ", connectTimeoutNanos="
-        + connectTimeoutNanos
-        + ", keepAliveTimeNanos="
-        + keepAliveTimeNanos
-        + ", keepAliveTimeoutNanos="
-        + keepAliveTimeoutNanos
-        + ", keepAliveWithoutCalls="
-        + keepAliveWithoutCalls
-        + ", idleTimeoutNanos="
-        + idleTimeoutNanos
-        + '}';
-  }
-
   /** Builder for <code>ConnectParam</code> */
   public static class Builder {
     // Optional parameters - initialized to default values
     private String host = "localhost";
-    private String port = "19530";
+    private int port = 19530;
     private long connectTimeoutNanos = TimeUnit.NANOSECONDS.convert(10, TimeUnit.SECONDS);
     private long keepAliveTimeNanos = Long.MAX_VALUE; // Disabling keepalive
     private long keepAliveTimeoutNanos = TimeUnit.NANOSECONDS.convert(20, TimeUnit.SECONDS);
@@ -120,9 +98,8 @@ public class ConnectParam {
      * @param port server port
      * @return <code>Builder</code>
      */
-    public Builder withPort(@Nonnull String port) throws IllegalArgumentException {
-      int portInt = Integer.parseInt(port);
-      if (portInt < 0 || portInt > 0xFFFF) {
+    public Builder withPort(int port) throws IllegalArgumentException {
+      if (port < 0 || port > 0xFFFF) {
         throw new IllegalArgumentException("Port is out of range!");
       }
       this.port = port;

+ 0 - 77
src/main/java/io/milvus/client/CreateIndexParam.java

@@ -1,77 +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.client;
-
-import javax.annotation.Nonnull;
-
-/** Contains parameters for <code>createIndex</code> */
-public class CreateIndexParam {
-
-  private final String tableName;
-  private final Index index;
-
-  private CreateIndexParam(@Nonnull Builder builder) {
-    this.tableName = builder.tableName;
-    this.index = builder.index;
-  }
-
-  public String getTableName() {
-    return tableName;
-  }
-
-  public Index getIndex() {
-    return index;
-  }
-
-  @Override
-  public String toString() {
-    return "CreateIndexParam{" + "tableName='" + tableName + '\'' + ", index=" + index + '}';
-  }
-
-  /** Builder for <code>CreateIndexParam</code> */
-  public static class Builder {
-    // Required parameters
-    private final String tableName;
-
-    // Optional parameters - initialized to default values
-    private Index index;
-
-    /** @param tableName table to create index on */
-    public Builder(@Nonnull String tableName) {
-      this.tableName = tableName;
-    }
-
-    /**
-     * Optional. Default to Index{indexType = IndexType.FLAT, nList = 16384}
-     *
-     * @param index a <code>Index</code> object
-     * @return <code>Builder</code>
-     * @see Index
-     */
-    public Builder withIndex(Index index) {
-      this.index = index;
-      return this;
-    }
-
-    public CreateIndexParam build() {
-      return new CreateIndexParam(this);
-    }
-  }
-}

+ 0 - 56
src/main/java/io/milvus/client/DateRange.java

@@ -1,56 +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.client;
-
-import javax.annotation.Nonnull;
-import java.util.Date;
-
-/** Represents a date range [<code>startDate</code>, <code>endDate</code>) */
-public class DateRange {
-  private Date startDate;
-  private Date endDate;
-
-  /** @see Date */
-  public DateRange(@Nonnull Date startDate, @Nonnull Date endDate) {
-    this.startDate = startDate;
-    this.endDate = endDate;
-  }
-
-  public Date getStartDate() {
-    return startDate;
-  }
-
-  public void setStartDate(@Nonnull Date startDate) {
-    this.startDate = startDate;
-  }
-
-  public Date getEndDate() {
-    return endDate;
-  }
-
-  public void setEndDate(@Nonnull Date endDate) {
-    this.endDate = endDate;
-  }
-
-  @Override
-  public String toString() {
-    return "{startDate=" + startDate + ", endDate=" + endDate + '}';
-  }
-}

+ 14 - 11
src/main/java/io/milvus/client/DescribeTableResponse.java → src/main/java/io/milvus/client/DescribeCollectionResponse.java

@@ -23,31 +23,33 @@ import javax.annotation.Nullable;
 import java.util.Optional;
 
 /**
- * Contains the returned <code>response</code> and <code>tableSchema</code> for <code>describeTable
+ * Contains the returned <code>response</code> and <code>collectionMapping</code> for <code>
+ * describeCollection
  * </code>
  */
-public class DescribeTableResponse {
+public class DescribeCollectionResponse {
   private final Response response;
-  private final TableSchema tableSchema;
+  private final CollectionMapping collectionMapping;
 
-  DescribeTableResponse(Response response, @Nullable TableSchema tableSchema) {
+  DescribeCollectionResponse(Response response, @Nullable CollectionMapping collectionMapping) {
     this.response = response;
-    this.tableSchema = tableSchema;
+    this.collectionMapping = collectionMapping;
   }
 
   /**
-   * @return an <code>Optional</code> object which may or may not contain a <code>TableSchema</code>
-   *     object
+   * @return an <code>Optional</code> object which may or may not contain a <code>CollectionMapping
+   *     </code> object
    * @see Optional
    */
-  public Optional<TableSchema> getTableSchema() {
-    return Optional.ofNullable(tableSchema);
+  public Optional<CollectionMapping> getCollectionMapping() {
+    return Optional.ofNullable(collectionMapping);
   }
 
   public Response getResponse() {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }
@@ -55,7 +57,8 @@ public class DescribeTableResponse {
   @Override
   public String toString() {
     return String.format(
-        "DescribeTableResponse {%s, %s}",
-        response.toString(), tableSchema == null ? "Table schema = None" : tableSchema.toString());
+        "DescribeCollectionResponse {%s, %s}",
+        response.toString(),
+        collectionMapping == null ? "Collection mapping = None" : collectionMapping.toString());
   }
 }

+ 1 - 0
src/main/java/io/milvus/client/DescribeIndexResponse.java

@@ -47,6 +47,7 @@ public class DescribeIndexResponse {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }

+ 12 - 8
src/main/java/io/milvus/client/HasTableResponse.java → src/main/java/io/milvus/client/GetCollectionRowCountResponse.java

@@ -20,31 +20,35 @@
 package io.milvus.client;
 
 /**
- * Contains the returned <code>response</code> and <code>hasTable</code> for <code>hasTable</code>
+ * Contains the returned <code>response</code> and <code>collectionRowCount</code> for <code>
+ * getCollectionRowCount</code>
  */
-public class HasTableResponse {
+public class GetCollectionRowCountResponse {
   private final Response response;
-  private final boolean hasTable;
+  private final long collectionRowCount;
 
-  HasTableResponse(Response response, boolean hasTable) {
+  GetCollectionRowCountResponse(Response response, long collectionRowCount) {
     this.response = response;
-    this.hasTable = hasTable;
+    this.collectionRowCount = collectionRowCount;
   }
 
-  public boolean hasTable() {
-    return hasTable;
+  public long getCollectionRowCount() {
+    return collectionRowCount;
   }
 
   public Response getResponse() {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }
 
   @Override
   public String toString() {
-    return String.format("HasTableResponse {%s, has table = %s}", response.toString(), hasTable);
+    return String.format(
+        "CountCollectionResponse {%s, collection row count = %d}",
+        response.toString(), collectionRowCount);
   }
 }

+ 59 - 0
src/main/java/io/milvus/client/GetVectorByIdResponse.java

@@ -0,0 +1,59 @@
+package io.milvus.client;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Contains the returned <code>response</code> and either a <code>floatVector</code> or a <code>
+ * binaryVector</code> for <code>getVectorById</code>. If the id does not exist, both returned
+ * vectors will be empty.
+ */
+public class GetVectorByIdResponse {
+  private final Response response;
+  private final List<Float> floatVector;
+  private final ByteBuffer binaryVector;
+
+  GetVectorByIdResponse(Response response, List<Float> floatVector, ByteBuffer binaryVector) {
+    this.response = response;
+    this.floatVector = floatVector;
+    this.binaryVector = binaryVector;
+  }
+
+  public List<Float> getFloatVector() {
+    return floatVector;
+  }
+
+  /**
+   * @return an <code>Optional</code> object which may or may not contain a <code>ByteBuffer</code>
+   *     object
+   * @see Optional
+   */
+  public Optional<ByteBuffer> getBinaryVector() {
+    return Optional.ofNullable(binaryVector);
+  }
+
+  /** @return <code>true</code> if the id corresponds to a float vector */
+  public boolean isFloatVector() {
+    return !floatVector.isEmpty();
+  }
+
+  /** @return <code>true</code> if the id corresponds to a binary vector */
+  public boolean isBinaryVector() {
+    return binaryVector != null && binaryVector.hasRemaining();
+  }
+
+  /** @return <code>true</code> if the id's corresponding vector exists */
+  public boolean exists() {
+    return isFloatVector() || isBinaryVector();
+  }
+
+  public Response getResponse() {
+    return response;
+  }
+
+  /** @return <code>true</code> if the response status equals SUCCESS */
+  public boolean ok() {
+    return response.ok();
+  }
+}

+ 30 - 0
src/main/java/io/milvus/client/GetVectorIdsResponse.java

@@ -0,0 +1,30 @@
+package io.milvus.client;
+
+import java.util.List;
+
+/**
+ * Contains the returned <code>response</code> and a <code>List</code> of ids present in a segment
+ * for <code>getVectorIds</code>.
+ */
+public class GetVectorIdsResponse {
+  private final Response response;
+  private final List<Long> ids;
+
+  GetVectorIdsResponse(Response response, List<Long> ids) {
+    this.response = response;
+    this.ids = ids;
+  }
+
+  public List<Long> getIds() {
+    return ids;
+  }
+
+  public Response getResponse() {
+    return response;
+  }
+
+  /** @return <code>true</code> if the response status equals SUCCESS */
+  public boolean ok() {
+    return response.ok();
+  }
+}

+ 10 - 9
src/main/java/io/milvus/client/GetTableRowCountResponse.java → src/main/java/io/milvus/client/HasCollectionResponse.java

@@ -20,26 +20,27 @@
 package io.milvus.client;
 
 /**
- * Contains the returned <code>response</code> and <code>tableRowCount</code> for <code>
- * getTableRowCount</code>
+ * Contains the returned <code>response</code> and <code>hasCollection</code> for <code>
+ * hasCollection</code>
  */
-public class GetTableRowCountResponse {
+public class HasCollectionResponse {
   private final Response response;
-  private final long tableRowCount;
+  private final boolean hasCollection;
 
-  GetTableRowCountResponse(Response response, long tableRowCount) {
+  HasCollectionResponse(Response response, boolean hasCollection) {
     this.response = response;
-    this.tableRowCount = tableRowCount;
+    this.hasCollection = hasCollection;
   }
 
-  public long getTableRowCount() {
-    return tableRowCount;
+  public boolean hasCollection() {
+    return hasCollection;
   }
 
   public Response getResponse() {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }
@@ -47,6 +48,6 @@ public class GetTableRowCountResponse {
   @Override
   public String toString() {
     return String.format(
-        "CountTableResponse {%s, table row count = %d}", response.toString(), tableRowCount);
+        "HasCollectionResponse {%s, has collection = %s}", response.toString(), hasCollection);
   }
 }

+ 51 - 16
src/main/java/io/milvus/client/Index.java

@@ -23,52 +23,87 @@ import javax.annotation.Nonnull;
 
 /** Represents an index containing <code>indexType</code> and <code>nList</code> */
 public class Index {
+  private final String collectionName;
   private final IndexType indexType;
-  private final int nList;
+  private final String paramsInJson;
 
   private Index(@Nonnull Builder builder) {
+    this.collectionName = builder.collectionName;
     this.indexType = builder.indexType;
-    this.nList = builder.nList;
+    this.paramsInJson = builder.paramsInJson;
+  }
+
+  public String getCollectionName() {
+    return collectionName;
   }
 
   public IndexType getIndexType() {
     return indexType;
   }
 
-  public int getNList() {
-    return nList;
+  public String getParamsInJson() {
+    return paramsInJson;
   }
 
   @Override
   public String toString() {
-    return "Index {" + "indexType=" + indexType + ", nList=" + nList + '}';
+    return "Index {"
+        + "collectionName="
+        + collectionName
+        + ", indexType="
+        + indexType
+        + ", params="
+        + paramsInJson
+        + '}';
   }
 
   /** Builder for <code>Index</code> */
   public static class Builder {
+    // Required parameters
+    private final String collectionName;
+    private final IndexType indexType;
+
     // Optional parameters - initialized to default values
-    private IndexType indexType = IndexType.FLAT;
-    private int nList = 16384;
+    private String paramsInJson;
 
     /**
-     * Optional. Default to <code>IndexType.FLAT</code>
-     *
+     * @param collectionName collection to create index on
      * @param indexType a <code>IndexType</code> object
-     * @return <code>Builder</code>
      */
-    public Builder withIndexType(@Nonnull IndexType indexType) {
+    public Builder(@Nonnull String collectionName, @Nonnull IndexType indexType) {
+      this.collectionName = collectionName;
       this.indexType = indexType;
-      return this;
     }
 
     /**
-     * Optional. Default to 16384.
+     * Optional. Default to empty <code>String</code>.
+     *
+     * <pre>
+     * For different index type, index parameter is different accordingly, for example:
+     *
+     * FLAT/IVFLAT/SQ8: {"nlist": 16384}
+     * nlist range:[1, 999999]
+     *
+     * IVFPQ: {"nlist": 16384, "m": 12}
+     * nlist range:[1, 999999]
+     * m is decided by dim and have a couple of results.
+     *
+     * NSG: {"search_length": 45, "out_degree": 50, "candidate_pool_size": 300, "knng": 100}
+     * search_length range:[10, 300]
+     * out_degree range:[5, 300]
+     * candidate_pool_size range:[50, 1000]
+     * knng range:[5, 300]
+     *
+     * HNSW: {"M": 16, "efConstruction": 500}
+     * M range:[5, 48]
+     * efConstruction range:[100, 500]
+     * </pre>
      *
-     * @param nList nList of the index
+     * @param paramsInJson extra parameters in JSON format
      * @return <code>Builder</code>
      */
-    public Builder withNList(int nList) {
-      this.nList = nList;
+    public Builder withParamsInJson(@Nonnull String paramsInJson) {
+      this.paramsInJson = paramsInJson;
       return this;
     }
 

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

@@ -23,7 +23,7 @@ import java.util.Arrays;
 import java.util.Optional;
 
 /**
- * Represents different types of indexing method to query the table:
+ * Represents different types of indexing method to query the collection:
  *
  * <pre>
  *
@@ -34,7 +34,7 @@ import java.util.Optional;
  * 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. NSG - NSG (Navigating Spreading-out Graph) is a graph-base search algorithm that a) lowers the average
+ * 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
@@ -46,7 +46,9 @@ import java.util.Optional;
  *
  * 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 inevitable trade-off between memory and search accuracy.
+ * 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>
  */
@@ -55,9 +57,10 @@ public enum IndexType {
   FLAT(1),
   IVFLAT(2),
   IVF_SQ8(3),
-  NSG(4),
+  RNSG(4),
   IVF_SQ8_H(5),
   IVF_PQ(6),
+  HNSW(11),
 
   UNKNOWN(-1);
 

+ 46 - 16
src/main/java/io/milvus/client/InsertParam.java

@@ -20,29 +20,36 @@
 package io.milvus.client;
 
 import javax.annotation.Nonnull;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 
 /** Contains parameters for <code>insert</code> */
 public class InsertParam {
-  private final String tableName;
-  private final List<List<Float>> vectors;
+  private final String collectionName;
+  private final List<List<Float>> floatVectors;
+  private final List<ByteBuffer> binaryVectors;
   private final List<Long> vectorIds;
   private final String partitionTag;
 
   private InsertParam(@Nonnull Builder builder) {
-    this.tableName = builder.tableName;
-    this.vectors = builder.vectors;
+    this.collectionName = builder.collectionName;
+    this.floatVectors = builder.floatVectors;
+    this.binaryVectors = builder.binaryVectors;
     this.vectorIds = builder.vectorIds;
     this.partitionTag = builder.partitionTag;
   }
 
-  public String getTableName() {
-    return tableName;
+  public String getCollectionName() {
+    return collectionName;
   }
 
-  public List<List<Float>> getVectors() {
-    return vectors;
+  public List<List<Float>> getFloatVectors() {
+    return floatVectors;
+  }
+
+  public List<ByteBuffer> getBinaryVectors() {
+    return binaryVectors;
   }
 
   public List<Long> getVectorIds() {
@@ -56,21 +63,44 @@ public class InsertParam {
   /** Builder for <code>InsertParam</code> */
   public static class Builder {
     // Required parameters
-    private final String tableName;
-    private final List<List<Float>> vectors;
+    private final String collectionName;
 
     // Optional parameters - initialized to default values
+    private List<List<Float>> floatVectors = new ArrayList<>();
+    private List<ByteBuffer> binaryVectors = new ArrayList<>();
     private List<Long> vectorIds = new ArrayList<>();
     private String partitionTag = "";
 
+    /** @param collectionName collection to insert vectors to */
+    public Builder(@Nonnull String collectionName) {
+      this.collectionName = collectionName;
+    }
+
+    /**
+     * Default to an empty <code>ArrayList</code>. You can only insert either float or binary
+     * vectors to a collection, not both.
+     *
+     * @param floatVectors a <code>List</code> of float vectors to insert. Each inner <code>List
+     *     </code> represents a float vector.
+     * @return <code>Builder</code>
+     */
+    public Builder withFloatVectors(@Nonnull List<List<Float>> floatVectors) {
+      this.floatVectors = floatVectors;
+      return this;
+    }
+
     /**
-     * @param tableName table to insert vectors to
-     * @param vectors a <code>List</code> of vectors to insert. Each inner <code>List</code>
-     *     represents a vector.
+     * Default to an empty <code>ArrayList</code>. You can only insert either float or binary
+     * vectors to a collection, not both.
+     *
+     * @param binaryVectors a <code>List</code> of binary vectors to insert. Each <code>ByteBuffer
+     *     </code> object represents a binary vector, with every 8 bits constituting a byte.
+     * @return <code>Builder</code>
+     * @see ByteBuffer
      */
-    public Builder(@Nonnull String tableName, @Nonnull List<List<Float>> vectors) {
-      this.tableName = tableName;
-      this.vectors = vectors;
+    public Builder withBinaryVectors(@Nonnull List<ByteBuffer> binaryVectors) {
+      this.binaryVectors = binaryVectors;
+      return this;
     }
 
     /**

+ 1 - 0
src/main/java/io/milvus/client/InsertResponse.java

@@ -41,6 +41,7 @@ public class InsertResponse {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }

+ 9 - 2
src/main/java/io/milvus/client/MetricType.java

@@ -24,10 +24,17 @@ import java.util.Optional;
 
 /** Represents available metric types */
 public enum MetricType {
-  /** Euclidean distance */
+  INVALID(0),
+  /** Euclidean distance. For float vectors only */
   L2(1),
-  /** Inner product */
+  /** Inner product. For float vectors only */
   IP(2),
+  /** Hamming distance. For binary vectors only */
+  HAMMING(3),
+  /** Jaccard distance. For binary vectors only */
+  JACCARD(4),
+  /** Tanimoto distance. For binary vectors only */
+  TANIMOTO(5),
 
   UNKNOWN(-1);
 

+ 159 - 91
src/main/java/io/milvus/client/MilvusClient.java

@@ -19,12 +19,14 @@
 
 package io.milvus.client;
 
+import java.util.List;
+
 /** The Milvus Client Interface */
 public interface MilvusClient {
 
-  String clientVersion = "0.4.1";
+  String clientVersion = "0.5.0";
 
-  /** @return the current Milvus client version */
+  /** @return current Milvus client version: 0.5.0 */
   default String getClientVersion() {
     return clientVersion;
   }
@@ -38,7 +40,7 @@ public interface MilvusClient {
    * <code>
    * ConnectParam connectParam = new ConnectParam.Builder()
    *                                             .withHost("localhost")
-   *                                             .withPort("19530")
+   *                                             .withPort(19530)
    *                                             .withConnectTimeout(10, TimeUnit.SECONDS)
    *                                             .withKeepAliveTime(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
    *                                             .withKeepAliveTimeout(20, TimeUnit.SECONDS)
@@ -57,7 +59,7 @@ public interface MilvusClient {
   Response connect(ConnectParam connectParam) throws ConnectFailedException;
 
   /**
-   * @return <code>true</code> if the client is connected to Milvus server. The channel's
+   * @return <code>true</code> if the client is connected to Milvus server and the channel's
    *     connectivity state is READY.
    */
   boolean isConnected();
@@ -72,13 +74,13 @@ public interface MilvusClient {
   Response disconnect() throws InterruptedException;
 
   /**
-   * Creates table specified by <code>tableSchemaParam</code>
+   * Creates collection specified by <code>collectionMapping</code>
    *
-   * @param tableSchema the <code>TableSchema</code> object
+   * @param collectionMapping the <code>CollectionMapping</code> object
    *     <pre>
    * example usage:
    * <code>
-   * TableSchema tableSchema = new TableSchema.Builder(tableName, dimension)
+   * CollectionMapping collectionMapping = new CollectionMapping.Builder(collectionName, dimension)
    *                                          .withIndexFileSize(1024)
    *                                          .withMetricType(MetricType.IP)
    *                                          .build();
@@ -86,99 +88,79 @@ public interface MilvusClient {
    * </pre>
    *
    * @return <code>Response</code>
-   * @see TableSchema
+   * @see CollectionMapping
    * @see MetricType
    * @see Response
    */
-  Response createTable(TableSchema tableSchema);
+  Response createCollection(CollectionMapping collectionMapping);
 
   /**
-   * Check whether table exists
+   * Checks whether the collection exists
    *
-   * @param tableName table to check
-   * @return <code>HasTableResponse</code>
-   * @see HasTableResponse
+   * @param collectionName collection to check
+   * @return <code>HasCollectionResponse</code>
+   * @see HasCollectionResponse
    * @see Response
    */
-  HasTableResponse hasTable(String tableName);
+  HasCollectionResponse hasCollection(String collectionName);
 
   /**
-   * Drops table
+   * Drops collection
    *
-   * @param tableName table to drop
+   * @param collectionName collection to drop
    * @return <code>Response</code>
    * @see Response
    */
-  Response dropTable(String tableName);
+  Response dropCollection(String collectionName);
 
   /**
-   * Creates index specified by <code>indexParam</code>
+   * Creates index specified by <code>index</code>
    *
-   * @param createIndexParam the <code>CreateIndexParam</code> object
+   * @param index the <code>Index</code> object
    *     <pre>
    * example usage:
    * <code>
-   * Index index = new Index.Builder()
-   *                        .withIndexType(IndexType.IVF_SQ8)
-   *                        .withNList(16384)
+   * Index index = new Index.Builder(collectionName, IndexType.IVF_SQ8)
+   *                        .withParamsInJson("{\"nlist\": 16384}")
    *                        .build();
-   * CreateIndexParam createIndexParam = new CreateIndexParam.Builder(tableName)
-   *                                                         .withIndex(index)
-   *                                                         .build();
    * </code>
    * </pre>
    *
    * @return <code>Response</code>
    * @see Index
-   * @see CreateIndexParam
    * @see IndexType
    * @see Response
    */
-  Response createIndex(CreateIndexParam createIndexParam);
+  Response createIndex(Index index);
 
   /**
-   * Creates a partition specified by <code>PartitionParam</code>
-   *
-   * @param partition the <code>PartitionParam</code> object
-   *     <pre>
-   * example usage:
-   * <code>
-   * Partition partition = new Partition.Builder(tableName, partitionName, tag).build();
-   * </code>
-   * </pre>
+   * Creates a partition specified by <code>collectionName</code> and <code>tag</code>
    *
+   * @param collectionName collection name
+   * @param tag partition tag
    * @return <code>Response</code>
-   * @see Partition
    * @see Response
    */
-  Response createPartition(Partition partition);
+  Response createPartition(String collectionName, String tag);
 
   /**
-   * Shows current partitions of a table
+   * Shows current partitions of a collection
    *
-   * @param tableName table name
+   * @param collectionName collection name
    * @return <code>ShowPartitionsResponse</code>
    * @see ShowPartitionsResponse
    * @see Response
    */
-  ShowPartitionsResponse showPartitions(String tableName);
+  ShowPartitionsResponse showPartitions(String collectionName);
 
   /**
-   * Drops partition specified by <code>partitionName</code>
+   * Drops partition specified by <code>collectionName</code> and <code>tag</code>
    *
-   * @param partitionName partition name
-   * @see Response
-   */
-  Response dropPartition(String partitionName);
-
-  /**
-   * Drops partition specified by <code>tableName</code> and <code>tag</code>
-   *
-   * @param tableName table name
+   * @param collectionName collection name
    * @param tag partition tag
    * @see Response
    */
-  Response dropPartition(String tableName, String tag);
+  Response dropPartition(String collectionName, String tag);
 
   /**
    * Inserts data specified by <code>insertParam</code>
@@ -187,7 +169,8 @@ public interface MilvusClient {
    *     <pre>
    * example usage:
    * <code>
-   * InsertParam insertParam = new InsertParam.Builder(tableName, vectors)
+   * InsertParam insertParam = new InsertParam.Builder(collectionName)
+   *                                          .withFloatVectors(floatVectors)
    *                                          .withVectorIds(vectorIds)
    *                                          .withPartitionTag(tag)
    *                                          .build();
@@ -208,18 +191,17 @@ public interface MilvusClient {
    *     <pre>
    * example usage:
    * <code>
-   * SearchParam searchParam = new SearchParam.Builder(tableName, vectorsToSearch)
+   * SearchParam searchParam = new SearchParam.Builder(collectionName)
+   *                                          .withFloatVectors(floatVectors)
    *                                          .withTopK(topK)
-   *                                          .withNProbe(nProbe)
-   *                                          .withDateRanges(dateRanges)
    *                                          .withPartitionTags(partitionTagsList)
+   *                                          .withParamsInJson("{\"nprobe\": 20}")
    *                                          .build();
    * </code>
    * </pre>
    *
    * @return <code>SearchResponse</code>
    * @see SearchParam
-   * @see DateRange
    * @see SearchResponse
    * @see SearchResponse.QueryResult
    * @see Response
@@ -227,63 +209,61 @@ public interface MilvusClient {
   SearchResponse search(SearchParam searchParam);
 
   /**
-   * Searches vectors in specific files specified by <code>searchInFilesParam</code>
+   * Searches vectors in specific files
    *
-   * @param searchInFilesParam the <code>SearchInFilesParam</code> object
+   * @param fileIds list of file ids to search from
+   * @param searchParam the <code>SearchParam</code> object
    *     <pre>
    * example usage:
    * <code>
-   * SearchParam searchParam = new SearchParam.Builder(tableName, vectorsToSearch)
+   * SearchParam searchParam = new SearchParam.Builder(collectionName)
+   *                                          .withFloatVectors(floatVectors)
    *                                          .withTopK(topK)
-   *                                          .withNProbe(nProbe)
-   *                                          .withDateRanges(dateRanges)
    *                                          .withPartitionTags(partitionTagsList)
+   *                                          .withParamsInJson("{\"nprobe\": 20}")
    *                                          .build();
-   * SearchInFilesParam searchInFilesParam = new SearchInFilesParam.Builder(fileIds, searchParam)
-   *                                                               .build();
    * </code>
    * </pre>
    *
    * @return <code>SearchResponse</code>
-   * @see SearchInFilesParam
    * @see SearchParam
-   * @see DateRange
    * @see SearchResponse
    * @see SearchResponse.QueryResult
    * @see Response
    */
-  SearchResponse searchInFiles(SearchInFilesParam searchInFilesParam);
+  SearchResponse searchInFiles(List<String> fileIds, SearchParam searchParam);
 
   /**
-   * Describes table
+   * Describes the collection
    *
-   * @param tableName table to describe
-   * @see DescribeTableResponse
+   * @param collectionName collection to describe
+   * @see DescribeCollectionResponse
+   * @see CollectionMapping
    * @see Response
    */
-  DescribeTableResponse describeTable(String tableName);
+  DescribeCollectionResponse describeCollection(String collectionName);
 
   /**
-   * Shows current tables
+   * Shows current collections
    *
-   * @return <code>ShowTablesResponse</code>
-   * @see ShowTablesResponse
+   * @return <code>ShowCollectionsResponse</code>
+   * @see ShowCollectionsResponse
    * @see Response
    */
-  ShowTablesResponse showTables();
+  ShowCollectionsResponse showCollections();
 
   /**
-   * Gets current row count of table
+   * Gets current row count of a collection
    *
-   * @param tableName table to count
-   * @return <code>GetTableRowCountResponse</code>
-   * @see GetTableRowCountResponse
+   * @param collectionName collection to get row count
+   * @return <code>GetCollectionRowCountResponse</code>
+   * @see GetCollectionRowCountResponse
    * @see Response
    */
-  GetTableRowCountResponse getTableRowCount(String tableName);
+  GetCollectionRowCountResponse getCollectionRowCount(String collectionName);
 
   /**
-   * Prints server status
+   * Get server status
    *
    * @return <code>Response</code>
    * @see Response
@@ -291,7 +271,7 @@ public interface MilvusClient {
   Response getServerStatus();
 
   /**
-   * Prints server version
+   * Get server version
    *
    * @return <code>Response</code>
    * @see Response
@@ -299,29 +279,117 @@ public interface MilvusClient {
   Response getServerVersion();
 
   /**
-   * Pre-loads table to memory
+   * Sends a command to server
+   *
+   * @return <code>Response</code> command's response will be return in <code>message</code>
+   * @see Response
+   */
+  Response command(String command);
+
+  /**
+   * Pre-loads collection to memory
    *
-   * @param tableName table to preload
+   * @param collectionName collection to preload
    * @return <code>Response</code>
    * @see Response
    */
-  Response preloadTable(String tableName);
+  Response preloadCollection(String collectionName);
 
   /**
-   * Describes table index
+   * Describes collection index
    *
-   * @param tableName table to describe index of
+   * @param collectionName collection to describe index of
    * @see DescribeIndexResponse
    * @see Index
    * @see Response
    */
-  DescribeIndexResponse describeIndex(String tableName);
+  DescribeIndexResponse describeIndex(String collectionName);
+
+  /**
+   * Drops collection index
+   *
+   * @param collectionName collection to drop index of
+   * @see Response
+   */
+  Response dropIndex(String collectionName);
+
+  /**
+   * Shows collection information. A collection consists of one or multiple partitions (including
+   * the default partition), and a partitions consists of one or more segments. Each partition or
+   * segment can be uniquely identified by its partition tag or segment name respectively.
+   *
+   * @param collectionName collection to show info from
+   * @see ShowCollectionInfoResponse
+   * @see CollectionInfo
+   * @see CollectionInfo.PartitionInfo
+   * @see CollectionInfo.PartitionInfo.SegmentInfo
+   * @see Response
+   */
+  ShowCollectionInfoResponse showCollectionInfo(String collectionName);
+
+  /**
+   * Gets either a float or binary vector by id.
+   *
+   * @param collectionName collection to get vector from
+   * @param id vector id
+   * @see GetVectorByIdResponse
+   * @see Response
+   */
+  GetVectorByIdResponse getVectorById(String collectionName, Long id);
+
+  /**
+   * Gets all vector ids in a segment
+   *
+   * @param collectionName collection to get vector ids from
+   * @param segmentName segment name
+   * @see GetVectorIdsResponse
+   * @see Response
+   */
+  GetVectorIdsResponse getVectorIds(String collectionName, String segmentName);
+
+  /**
+   * Deletes data in a collection by a list of ids
+   *
+   * @param collectionName collection to delete ids from
+   * @param ids a <code>List</code> of vector ids to delete
+   * @see Response
+   */
+  Response deleteByIds(String collectionName, List<Long> ids);
+
+  /**
+   * Deletes data in a collection by a single id
+   *
+   * @param collectionName collection to delete id from
+   * @param id vector id to delete
+   * @see Response
+   */
+  Response deleteById(String collectionName, Long id);
+
+  /**
+   * Flushes data in a list collections. Newly inserted or modifications on data will be visible
+   * after <code>flush</code> returned
+   *
+   * @param collectionNames a <code>List</code> of collections to flush
+   * @see Response
+   */
+  Response flush(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
+   * @see Response
+   */
+  Response flush(String collectionName);
 
   /**
-   * Drops table index
+   * 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 tableName table to drop index of
+   * @param collectionName name of collection to compact
    * @see Response
    */
-  Response dropIndex(String tableName);
+  Response compact(String collectionName);
 }

+ 445 - 238
src/main/java/io/milvus/client/MilvusGrpcClient.java

@@ -19,18 +19,17 @@
 
 package io.milvus.client;
 
+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.PartitionParam;
 import org.apache.commons.collections4.ListUtils;
 
 import javax.annotation.Nonnull;
-import java.text.SimpleDateFormat;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -43,10 +42,25 @@ public class MilvusGrpcClient implements MilvusClient {
   private static final String ANSI_YELLOW = "\u001B[33m";
   private static final String ANSI_PURPLE = "\u001B[35m";
   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;
 
+  ////////////////////// Constructor //////////////////////
+  public MilvusGrpcClient() {
+    logger.setLevel(Level.ALL);
+  }
+
+  /**
+   * @param logLevel we currently have three levels of logs: <code>INFO</code>, <code>WARNING</code>
+   *     and <code>SEVERE</code>. You can also specify to be <code>Level.All</code> or <code>
+   *     Level.OFF</code>
+   * @see Level
+   */
+  public MilvusGrpcClient(Level logLevel) {
+    logger.setLevel(logLevel);
+  }
+
   /////////////////////// Client Calls///////////////////////
 
   @Override
@@ -59,8 +73,7 @@ public class MilvusGrpcClient implements MilvusClient {
     try {
 
       channel =
-          ManagedChannelBuilder.forAddress(
-                  connectParam.getHost(), Integer.parseInt(connectParam.getPort()))
+          ManagedChannelBuilder.forAddress(connectParam.getHost(), connectParam.getPort())
               .usePlaintext()
               .maxInboundMessageSize(Integer.MAX_VALUE)
               .keepAliveTime(
@@ -79,7 +92,7 @@ public class MilvusGrpcClient implements MilvusClient {
       final long checkFrequency = 100; // ms
       while (channel.getState(false) != ConnectivityState.READY) {
         if (timeout <= 0) {
-          logSevere("Connect timeout! {0}", connectParam.toString());
+          logSevere("Connect timeout!");
           throw new ConnectFailedException("Connect timeout");
         }
         TimeUnit.MILLISECONDS.sleep(checkFrequency);
@@ -90,14 +103,14 @@ public class MilvusGrpcClient implements MilvusClient {
 
     } catch (Exception e) {
       if (!(e instanceof ConnectFailedException)) {
-        logSevere("Connect failed! {0}\n{1}", connectParam.toString(), e.toString());
+        logSevere("Connect failed! {0}", e.toString());
       }
       throw new ConnectFailedException("Exception occurred: " + e.toString());
     }
 
     logInfo(
         "Connection established successfully to host={0}, port={1}",
-        connectParam.getHost(), connectParam.getPort());
+        connectParam.getHost(), String.valueOf(connectParam.getPort()));
     return new Response(Response.Status.SUCCESS);
   }
 
@@ -132,7 +145,7 @@ public class MilvusGrpcClient implements MilvusClient {
   }
 
   @Override
-  public Response createTable(@Nonnull TableSchema tableSchema) {
+  public Response createCollection(@Nonnull CollectionMapping collectionMapping) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -141,10 +154,10 @@ public class MilvusGrpcClient implements MilvusClient {
 
     io.milvus.grpc.TableSchema request =
         io.milvus.grpc.TableSchema.newBuilder()
-            .setTableName(tableSchema.getTableName())
-            .setDimension(tableSchema.getDimension())
-            .setIndexFileSize(tableSchema.getIndexFileSize())
-            .setMetricType(tableSchema.getMetricType().getVal())
+            .setTableName(collectionMapping.getCollectionName())
+            .setDimension(collectionMapping.getDimension())
+            .setIndexFileSize(collectionMapping.getIndexFileSize())
+            .setMetricType(collectionMapping.getMetricType().getVal())
             .build();
 
     io.milvus.grpc.Status response;
@@ -153,57 +166,61 @@ public class MilvusGrpcClient implements MilvusClient {
       response = blockingStub.createTable(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Created table successfully!\n{0}", tableSchema.toString());
+        logInfo("Created collection successfully!\n{0}", collectionMapping.toString());
         return new Response(Response.Status.SUCCESS);
-      } else if (response.getReason().contentEquals("Table already exists")) {
-        logWarning("Table `{0}` already exists", tableSchema.getTableName());
+      } else if (response.getReason().contentEquals("Collection already exists")) {
+        logWarning("Collection `{0}` already exists", collectionMapping.getCollectionName());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       } else {
-        logSevere("Create table failed\n{0}\n{1}", tableSchema.toString(), response.toString());
+        logSevere(
+            "Create collection failed\n{0}\n{1}",
+            collectionMapping.toString(), response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
     } catch (StatusRuntimeException e) {
-      logSevere("createTable RPC failed:\n{0}", e.getStatus().toString());
+      logSevere("createCollection RPC failed:\n{0}", e.getStatus().toString());
       return new Response(Response.Status.RPC_ERROR, e.toString());
     }
   }
 
   @Override
-  public HasTableResponse hasTable(@Nonnull String tableName) {
+  public HasCollectionResponse hasCollection(@Nonnull String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
-      return new HasTableResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), false);
+      return new HasCollectionResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), false);
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.BoolReply response;
 
     try {
       response = blockingStub.hasTable(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("hasTable `{0}` = {1}", tableName, response.getBoolReply());
-        return new HasTableResponse(new Response(Response.Status.SUCCESS), response.getBoolReply());
+        logInfo("hasCollection `{0}` = {1}", collectionName, response.getBoolReply());
+        return new HasCollectionResponse(
+            new Response(Response.Status.SUCCESS), response.getBoolReply());
       } else {
-        logSevere("hasTable `{0}` failed:\n{1}", tableName, response.toString());
-        return new HasTableResponse(
+        logSevere("hasCollection `{0}` failed:\n{1}", collectionName, response.toString());
+        return new HasCollectionResponse(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 response.getStatus().getReason()),
             false);
       }
     } catch (StatusRuntimeException e) {
-      logSevere("hasTable RPC failed:\n{0}", e.getStatus().toString());
-      return new HasTableResponse(new Response(Response.Status.RPC_ERROR, e.toString()), false);
+      logSevere("hasCollection RPC failed:\n{0}", e.getStatus().toString());
+      return new HasCollectionResponse(
+          new Response(Response.Status.RPC_ERROR, e.toString()), false);
     }
   }
 
   @Override
-  public Response dropTable(@Nonnull String tableName) {
+  public Response dropCollection(@Nonnull String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -211,43 +228,44 @@ public class MilvusGrpcClient implements MilvusClient {
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.Status response;
 
     try {
       response = blockingStub.dropTable(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Dropped table `{0}` successfully!", tableName);
+        logInfo("Dropped collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
-        logSevere("Drop table `{0}` failed:\n{1}", tableName, response.toString());
+        logSevere("Drop collection `{0}` failed:\n{1}", collectionName, response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
     } catch (StatusRuntimeException e) {
-      logSevere("dropTable RPC failed:\n{0}", e.getStatus().toString());
+      logSevere("dropCollection RPC failed:\n{0}", e.getStatus().toString());
       return new Response(Response.Status.RPC_ERROR, e.toString());
     }
   }
 
   @Override
-  public Response createIndex(@Nonnull CreateIndexParam createIndexParam) {
+  public Response createIndex(@Nonnull Index index) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.Index index =
-        io.milvus.grpc.Index.newBuilder()
-            .setIndexType(createIndexParam.getIndex().getIndexType().getVal())
-            .setNlist(createIndexParam.getIndex().getNList())
+    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(createIndexParam.getTableName())
-            .setIndex(index)
+            .setTableName(index.getCollectionName())
+            .setIndexType(index.getIndexType().getVal())
+            .addExtraParams(extraParam)
             .build();
 
     io.milvus.grpc.Status response;
@@ -256,11 +274,10 @@ public class MilvusGrpcClient implements MilvusClient {
       response = blockingStub.createIndex(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Created index successfully!\n{0}", createIndexParam.toString());
+        logInfo("Created index successfully!\n{0}", index.toString());
         return new Response(Response.Status.SUCCESS);
       } else {
-        logSevere(
-            "Create index failed\n{0}\n{1}", createIndexParam.toString(), response.toString());
+        logSevere("Create index failed:\n{0}\n{1}", index.toString(), response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
@@ -271,7 +288,7 @@ public class MilvusGrpcClient implements MilvusClient {
   }
 
   @Override
-  public Response createPartition(Partition partition) {
+  public Response createPartition(String collectionName, String tag) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -279,11 +296,7 @@ public class MilvusGrpcClient implements MilvusClient {
     }
 
     io.milvus.grpc.PartitionParam request =
-        io.milvus.grpc.PartitionParam.newBuilder()
-            .setTableName(partition.getTableName())
-            .setPartitionName(partition.getPartitionName())
-            .setTag(partition.getTag())
-            .build();
+        io.milvus.grpc.PartitionParam.newBuilder().setTableName(collectionName).setTag(tag).build();
 
     io.milvus.grpc.Status response;
 
@@ -291,10 +304,12 @@ public class MilvusGrpcClient implements MilvusClient {
       response = blockingStub.createPartition(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Created partition successfully!\n{0}", partition.toString());
+        logInfo("Created partition `{0}` in collection `{1}` successfully!", tag, collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
-        logSevere("Create partition failed\n{0}\n{1}", partition.toString(), response.toString());
+        logSevere(
+            "Create partition `{0}` in collection `{1}` failed: {2}",
+            tag, collectionName, response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
@@ -305,7 +320,7 @@ public class MilvusGrpcClient implements MilvusClient {
   }
 
   @Override
-  public ShowPartitionsResponse showPartitions(String tableName) {
+  public ShowPartitionsResponse showPartitions(String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -314,25 +329,18 @@ public class MilvusGrpcClient implements MilvusClient {
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.PartitionList response;
 
     try {
       response = blockingStub.showPartitions(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        List<PartitionParam> partitionList = response.getPartitionArrayList();
-        List<Partition> partitions = new ArrayList<>();
-        for (PartitionParam partitionParam : partitionList) {
-          partitions.add(
-              new Partition.Builder(
-                      partitionParam.getTableName(),
-                      partitionParam.getPartitionName(),
-                      partitionParam.getTag())
-                  .build());
-        }
-        logInfo("Current partitions of table {0}: {1}", tableName, partitions.toString());
-        return new ShowPartitionsResponse(new Response(Response.Status.SUCCESS), partitions);
+        logInfo(
+            "Current partitions of collection {0}: {1}",
+            collectionName, response.getPartitionTagArrayList());
+        return new ShowPartitionsResponse(
+            new Response(Response.Status.SUCCESS), response.getPartitionTagArrayList());
       } else {
         logSevere("Show partitions failed:\n{0}", response.toString());
         return new ShowPartitionsResponse(
@@ -349,7 +357,7 @@ public class MilvusGrpcClient implements MilvusClient {
   }
 
   @Override
-  public Response dropPartition(String partitionName) {
+  public Response dropPartition(String collectionName, String tag) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -357,48 +365,19 @@ public class MilvusGrpcClient implements MilvusClient {
     }
 
     io.milvus.grpc.PartitionParam request =
-        io.milvus.grpc.PartitionParam.newBuilder().setPartitionName(partitionName).build();
+        io.milvus.grpc.PartitionParam.newBuilder().setTableName(collectionName).setTag(tag).build();
     io.milvus.grpc.Status response;
 
     try {
       response = blockingStub.dropPartition(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Dropped partition `{0}` successfully!", partitionName);
-        return new Response(Response.Status.SUCCESS);
-      } else {
-        logSevere("Drop partition `{0}` failed:\n{1}", partitionName, response.toString());
-        return new Response(
-            Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
-      }
-    } catch (StatusRuntimeException e) {
-      logSevere("dropPartition RPC failed:\n{0}", e.getStatus().toString());
-      return new Response(Response.Status.RPC_ERROR, e.toString());
-    }
-  }
-
-  @Override
-  public Response dropPartition(String tableName, String tag) {
-
-    if (!channelIsReadyOrIdle()) {
-      logWarning("You are not connected to Milvus server");
-      return new Response(Response.Status.CLIENT_NOT_CONNECTED);
-    }
-
-    io.milvus.grpc.PartitionParam request =
-        io.milvus.grpc.PartitionParam.newBuilder().setTableName(tableName).setTag(tag).build();
-    io.milvus.grpc.Status response;
-
-    try {
-      response = blockingStub.dropPartition(request);
-
-      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Dropped partition of table `{0}` and tag `{1}` successfully!", tableName, tag);
+        logInfo("Dropped partition `{1}` in collection `{1}` successfully!", tag, collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
         logSevere(
-            "Drop partition of table `{0}` and tag `{1}` failed:\n{1}",
-            tableName, tag, response.toString());
+            "Drop partition `{0}` in collection `{1}` failed:\n{1}",
+            tag, collectionName, response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
@@ -417,16 +396,12 @@ public class MilvusGrpcClient implements MilvusClient {
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
     }
 
-    List<io.milvus.grpc.RowRecord> rowRecordList = new ArrayList<>();
-    for (List<Float> vectors : insertParam.getVectors()) {
-      io.milvus.grpc.RowRecord rowRecord =
-          io.milvus.grpc.RowRecord.newBuilder().addAllVectorData(vectors).build();
-      rowRecordList.add(rowRecord);
-    }
+    List<io.milvus.grpc.RowRecord> rowRecordList =
+        buildRowRecordList(insertParam.getFloatVectors(), insertParam.getBinaryVectors());
 
     io.milvus.grpc.InsertParam request =
         io.milvus.grpc.InsertParam.newBuilder()
-            .setTableName(insertParam.getTableName())
+            .setTableName(insertParam.getCollectionName())
             .addAllRowRecordArray(rowRecordList)
             .addAllRowIdArray(insertParam.getVectorIds())
             .setPartitionTag(insertParam.getPartitionTag())
@@ -437,12 +412,11 @@ public class MilvusGrpcClient implements MilvusClient {
       response = blockingStub.insert(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        Optional<List<Long>> resultVectorIds = Optional.ofNullable(response.getVectorIdArrayList());
         logInfo(
-            "Inserted {0} vectors to table `{1}` successfully!",
-            resultVectorIds.map(List::size).orElse(0), insertParam.getTableName());
+            "Inserted {0} vectors to collection `{1}` successfully!",
+            response.getVectorIdArrayCount(), insertParam.getCollectionName());
         return new InsertResponse(
-            new Response(Response.Status.SUCCESS), resultVectorIds.orElse(new ArrayList<>()));
+            new Response(Response.Status.SUCCESS), response.getVectorIdArrayList());
       } else {
         logSevere("Insert vectors failed:\n{0}", response.toString());
         return new InsertResponse(
@@ -468,18 +442,22 @@ public class MilvusGrpcClient implements MilvusClient {
       return searchResponse;
     }
 
-    List<io.milvus.grpc.RowRecord> queryRowRecordList = getQueryRowRecordList(searchParam);
+    List<io.milvus.grpc.RowRecord> rowRecordList =
+        buildRowRecordList(searchParam.getFloatVectors(), searchParam.getBinaryVectors());
 
-    List<io.milvus.grpc.Range> queryRangeList = getQueryRangeList(searchParam);
+    io.milvus.grpc.KeyValuePair extraParam =
+        io.milvus.grpc.KeyValuePair.newBuilder()
+            .setKey(extraParamKey)
+            .setValue(searchParam.getParamsInJson())
+            .build();
 
     io.milvus.grpc.SearchParam request =
         io.milvus.grpc.SearchParam.newBuilder()
-            .setTableName(searchParam.getTableName())
-            .addAllQueryRecordArray(queryRowRecordList)
-            .addAllQueryRangeArray(queryRangeList)
-            .setTopk(searchParam.getTopK())
-            .setNprobe(searchParam.getNProbe())
+            .setTableName(searchParam.getCollectionName())
+            .addAllQueryRecordArray(rowRecordList)
             .addAllPartitionTagArray(searchParam.getPartitionTags())
+            .setTopk(searchParam.getTopK())
+            .addExtraParams(extraParam)
             .build();
 
     io.milvus.grpc.TopKQueryResult response;
@@ -512,7 +490,8 @@ public class MilvusGrpcClient implements MilvusClient {
   }
 
   @Override
-  public SearchResponse searchInFiles(@Nonnull SearchInFilesParam searchInFilesParam) {
+  public SearchResponse searchInFiles(
+      @Nonnull List<String> fileIds, @Nonnull SearchParam searchParam) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -521,26 +500,28 @@ public class MilvusGrpcClient implements MilvusClient {
       return searchResponse;
     }
 
-    SearchParam searchParam = searchInFilesParam.getSearchParam();
+    List<io.milvus.grpc.RowRecord> rowRecordList =
+        buildRowRecordList(searchParam.getFloatVectors(), searchParam.getBinaryVectors());
 
-    List<io.milvus.grpc.RowRecord> queryRowRecordList = getQueryRowRecordList(searchParam);
-
-    List<io.milvus.grpc.Range> queryRangeList = getQueryRangeList(searchParam);
+    io.milvus.grpc.KeyValuePair extraParam =
+        io.milvus.grpc.KeyValuePair.newBuilder()
+            .setKey(extraParamKey)
+            .setValue(searchParam.getParamsInJson())
+            .build();
 
-    io.milvus.grpc.SearchParam searchParamToSet =
+    io.milvus.grpc.SearchParam constructSearchParam =
         io.milvus.grpc.SearchParam.newBuilder()
-            .setTableName(searchParam.getTableName())
-            .addAllQueryRecordArray(queryRowRecordList)
-            .addAllQueryRangeArray(queryRangeList)
-            .setTopk(searchParam.getTopK())
-            .setNprobe(searchParam.getNProbe())
+            .setTableName(searchParam.getCollectionName())
+            .addAllQueryRecordArray(rowRecordList)
             .addAllPartitionTagArray(searchParam.getPartitionTags())
+            .setTopk(searchParam.getTopK())
+            .addExtraParams(extraParam)
             .build();
 
     io.milvus.grpc.SearchInFilesParam request =
         io.milvus.grpc.SearchInFilesParam.newBuilder()
-            .addAllFileIdArray(searchInFilesParam.getFileIds())
-            .setSearchParam(searchParamToSet)
+            .addAllFileIdArray(fileIds)
+            .setSearchParam(constructSearchParam)
             .build();
 
     io.milvus.grpc.TopKQueryResult response;
@@ -551,12 +532,12 @@ public class MilvusGrpcClient implements MilvusClient {
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
         SearchResponse searchResponse = buildSearchResponse(response);
         searchResponse.setResponse(new Response(Response.Status.SUCCESS));
-        logInfo("Search in files {0} completed successfully!", searchInFilesParam.getFileIds());
+        logInfo(
+            "Search in files completed successfully! Returned results for {0} queries",
+            searchResponse.getNumQueries());
         return searchResponse;
       } else {
-        logSevere(
-            "Search in files {0} failed:\n{1}",
-            searchInFilesParam.getFileIds(), response.toString());
+        logSevere("Search in files failed: {0}", response.toString());
 
         SearchResponse searchResponse = new SearchResponse();
         searchResponse.setResponse(
@@ -574,48 +555,51 @@ public class MilvusGrpcClient implements MilvusClient {
   }
 
   @Override
-  public DescribeTableResponse describeTable(@Nonnull String tableName) {
+  public DescribeCollectionResponse describeCollection(@Nonnull String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
-      return new DescribeTableResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
+      return new DescribeCollectionResponse(
+          new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.TableSchema response;
 
     try {
       response = blockingStub.describeTable(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        TableSchema tableSchema =
-            new TableSchema.Builder(response.getTableName(), response.getDimension())
+        CollectionMapping collectionMapping =
+            new CollectionMapping.Builder(response.getTableName(), response.getDimension())
                 .withIndexFileSize(response.getIndexFileSize())
                 .withMetricType(MetricType.valueOf(response.getMetricType()))
                 .build();
-        logInfo("Describe Table `{0}` returned:\n{1}", tableName, tableSchema);
-        return new DescribeTableResponse(new Response(Response.Status.SUCCESS), tableSchema);
+        logInfo("Describe Collection `{0}` returned:\n{1}", collectionName, collectionMapping);
+        return new DescribeCollectionResponse(
+            new Response(Response.Status.SUCCESS), collectionMapping);
       } else {
-        logSevere("Describe Table `{0}` failed:\n{1}", tableName, response.toString());
-        return new DescribeTableResponse(
+        logSevere("Describe Collection `{0}` failed:\n{1}", collectionName, response.toString());
+        return new DescribeCollectionResponse(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 response.getStatus().getReason()),
             null);
       }
     } catch (StatusRuntimeException e) {
-      logSevere("describeTable RPC failed:\n{0}", e.getStatus().toString());
-      return new DescribeTableResponse(new Response(Response.Status.RPC_ERROR, e.toString()), null);
+      logSevere("describeCollection RPC failed:\n{0}", e.getStatus().toString());
+      return new DescribeCollectionResponse(
+          new Response(Response.Status.RPC_ERROR, e.toString()), null);
     }
   }
 
   @Override
-  public ShowTablesResponse showTables() {
+  public ShowCollectionsResponse showCollections() {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
-      return new ShowTablesResponse(
+      return new ShowCollectionsResponse(
           new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
     }
 
@@ -626,60 +610,64 @@ public class MilvusGrpcClient implements MilvusClient {
       response = blockingStub.showTables(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        List<String> tableNames = response.getTableNamesList();
-        logInfo("Current tables: {0}", tableNames.toString());
-        return new ShowTablesResponse(new Response(Response.Status.SUCCESS), tableNames);
+        List<String> collectionNames = response.getTableNamesList();
+        logInfo("Current collections: {0}", collectionNames.toString());
+        return new ShowCollectionsResponse(new Response(Response.Status.SUCCESS), collectionNames);
       } else {
-        logSevere("Show tables failed:\n{0}", response.toString());
-        return new ShowTablesResponse(
+        logSevere("Show collections failed:\n{0}", response.toString());
+        return new ShowCollectionsResponse(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 response.getStatus().getReason()),
             new ArrayList<>());
       }
     } catch (StatusRuntimeException e) {
-      logSevere("showTables RPC failed:\n{0}", e.getStatus().toString());
-      return new ShowTablesResponse(
+      logSevere("showCollections RPC failed:\n{0}", e.getStatus().toString());
+      return new ShowCollectionsResponse(
           new Response(Response.Status.RPC_ERROR, e.toString()), new ArrayList<>());
     }
   }
 
   @Override
-  public GetTableRowCountResponse getTableRowCount(@Nonnull String tableName) {
+  public GetCollectionRowCountResponse getCollectionRowCount(@Nonnull String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
-      return new GetTableRowCountResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), 0);
+      return new GetCollectionRowCountResponse(
+          new Response(Response.Status.CLIENT_NOT_CONNECTED), 0);
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.TableRowCount response;
 
     try {
       response = blockingStub.countTable(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        long tableRowCount = response.getTableRowCount();
-        logInfo("Table `{0}` has {1} rows", tableName, tableRowCount);
-        return new GetTableRowCountResponse(new Response(Response.Status.SUCCESS), tableRowCount);
+        long collectionRowCount = response.getTableRowCount();
+        logInfo("Collection `{0}` has {1} rows", collectionName, collectionRowCount);
+        return new GetCollectionRowCountResponse(
+            new Response(Response.Status.SUCCESS), collectionRowCount);
       } else {
-        logSevere("Get table `{0}` row count failed:\n{1}", tableName, response.toString());
-        return new GetTableRowCountResponse(
+        logSevere(
+            "Get collection `{0}` row count failed:\n{1}", collectionName, response.toString());
+        return new GetCollectionRowCountResponse(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 response.getStatus().getReason()),
             0);
       }
     } catch (StatusRuntimeException e) {
-      logSevere("countTable RPC failed:\n{0}", e.getStatus().toString());
-      return new GetTableRowCountResponse(new Response(Response.Status.RPC_ERROR, e.toString()), 0);
+      logSevere("countCollection RPC failed:\n{0}", e.getStatus().toString());
+      return new GetCollectionRowCountResponse(
+          new Response(Response.Status.RPC_ERROR, e.toString()), 0);
     }
   }
 
   @Override
   public Response getServerStatus() {
-    return command("OK");
+    return command("status");
   }
 
   @Override
@@ -687,7 +675,7 @@ public class MilvusGrpcClient implements MilvusClient {
     return command("version");
   }
 
-  private Response command(@Nonnull String command) {
+  public Response command(@Nonnull String command) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -715,43 +703,82 @@ public class MilvusGrpcClient implements MilvusClient {
     }
   }
 
-  // TODO: make deleteByRange private for now
-  private Response deleteByRange(@Nonnull String tableName, @Nonnull DateRange dateRange) {
+  @Override
+  public Response preloadCollection(@Nonnull String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
-    io.milvus.grpc.DeleteByRangeParam request =
-        io.milvus.grpc.DeleteByRangeParam.newBuilder()
-            .setRange(getRange(dateRange))
-            .setTableName(tableName)
-            .build();
+    io.milvus.grpc.TableName request =
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.Status response;
 
     try {
-      response = blockingStub.deleteByRange(request);
+      response = blockingStub.preloadTable(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo(
-            "Deleted vectors from table `{0}` in range {1} successfully!", tableName, dateRange);
+        logInfo("Preloaded collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
-        logSevere(
-            "Deleted vectors from table `{0}` in range {1} failed:\n{2}",
-            tableName, dateRange, response.toString());
+        logSevere("Preload collection `{0}` failed:\n{1}", collectionName, response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
     } catch (StatusRuntimeException e) {
-      logSevere("deleteByRange RPC failed:\n{0}", e.getStatus().toString());
+      logSevere("preloadCollection RPC failed:\n{0}", e.getStatus().toString());
       return new Response(Response.Status.RPC_ERROR, e.toString());
     }
   }
 
   @Override
-  public Response preloadTable(@Nonnull String tableName) {
+  public DescribeIndexResponse describeIndex(@Nonnull String collectionName) {
+
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      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;
+
+    try {
+      response = blockingStub.describeIndex(request);
+
+      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+        String extraParam = "";
+        for (io.milvus.grpc.KeyValuePair kv : response.getExtraParamsList()) {
+          if (kv.getKey().contentEquals(extraParamKey)) {
+            extraParam = kv.getValue();
+          }
+        }
+        Index index =
+            new Index.Builder(response.getTableName(), IndexType.valueOf(response.getIndexType()))
+                .withParamsInJson(extraParam)
+                .build();
+        logInfo(
+            "Describe index for collection `{0}` returned:\n{1}", collectionName, index.toString());
+        return new DescribeIndexResponse(new Response(Response.Status.SUCCESS), index);
+      } else {
+        logSevere(
+            "Describe index for collection `{0}` failed:\n{1}",
+            collectionName, response.toString());
+        return new DescribeIndexResponse(
+            new Response(
+                Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                response.getStatus().getReason()),
+            null);
+      }
+    } catch (StatusRuntimeException e) {
+      logSevere("describeIndex RPC failed:\n{0}", e.getStatus().toString());
+      return new DescribeIndexResponse(new Response(Response.Status.RPC_ERROR, e.toString()), null);
+    }
+  }
+
+  @Override
+  public Response dropIndex(@Nonnull String collectionName) {
 
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
@@ -759,52 +786,76 @@ public class MilvusGrpcClient implements MilvusClient {
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.Status response;
 
     try {
-      response = blockingStub.preloadTable(request);
+      response = blockingStub.dropIndex(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Preloaded table `{0}` successfully!", tableName);
+        logInfo("Dropped index for collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
-        logSevere("Preload table `{0}` failed:\n{1}", tableName, response.toString());
+        logSevere(
+            "Drop index for collection `{0}` failed:\n{1}", collectionName, response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
     } catch (StatusRuntimeException e) {
-      logSevere("preloadTable RPC failed:\n{0}", e.getStatus().toString());
+      logSevere("dropIndex RPC failed:\n{0}", e.getStatus().toString());
       return new Response(Response.Status.RPC_ERROR, e.toString());
     }
   }
 
   @Override
-  public DescribeIndexResponse describeIndex(@Nonnull String tableName) {
-
+  public ShowCollectionInfoResponse showCollectionInfo(String collectionName) {
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
-      return new DescribeIndexResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
+      return new ShowCollectionInfoResponse(
+          new Response(Response.Status.CLIENT_NOT_CONNECTED), null);
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
-    io.milvus.grpc.IndexParam response;
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
+    io.milvus.grpc.TableInfo response;
 
     try {
-      response = blockingStub.describeIndex(request);
+      response = blockingStub.showTableInfo(request);
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        Index index =
-            new Index.Builder()
-                .withIndexType(IndexType.valueOf(response.getIndex().getIndexType()))
-                .withNList(response.getIndex().getNlist())
-                .build();
-        logInfo("Describe index for table `{0}` returned:\n{1}", tableName, index.toString());
-        return new DescribeIndexResponse(new Response(Response.Status.SUCCESS), index);
+
+        List<CollectionInfo.PartitionInfo> partitionInfos = new ArrayList<>();
+
+        for (io.milvus.grpc.PartitionStat partitionStat : response.getPartitionsStatList()) {
+
+          List<CollectionInfo.PartitionInfo.SegmentInfo> segmentInfos = new ArrayList<>();
+
+          for (io.milvus.grpc.SegmentStat segmentStat : partitionStat.getSegmentsStatList()) {
+
+            CollectionInfo.PartitionInfo.SegmentInfo segmentInfo =
+                new CollectionInfo.PartitionInfo.SegmentInfo(
+                    segmentStat.getSegmentName(),
+                    segmentStat.getRowCount(),
+                    segmentStat.getIndexName(),
+                    segmentStat.getDataSize());
+            segmentInfos.add(segmentInfo);
+          }
+
+          CollectionInfo.PartitionInfo partitionInfo =
+              new CollectionInfo.PartitionInfo(
+                  partitionStat.getTag(), partitionStat.getTotalRowCount(), segmentInfos);
+          partitionInfos.add(partitionInfo);
+        }
+
+        CollectionInfo collectionInfo =
+            new CollectionInfo(response.getTotalRowCount(), partitionInfos);
+
+        logInfo("ShowCollectionInfo for `{0}` returned successfully!", collectionName);
+        return new ShowCollectionInfoResponse(
+            new Response(Response.Status.SUCCESS), collectionInfo);
       } else {
-        logSevere("Describe index for table `{0}` failed:\n{1}", tableName, response.toString());
-        return new DescribeIndexResponse(
+        logSevere("ShowCollectionInfo for `{0}` failed:\n{1}", collectionName, response.toString());
+        return new ShowCollectionInfoResponse(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 response.getStatus().getReason()),
@@ -812,72 +863,228 @@ public class MilvusGrpcClient implements MilvusClient {
       }
     } catch (StatusRuntimeException e) {
       logSevere("describeIndex RPC failed:\n{0}", e.getStatus().toString());
-      return new DescribeIndexResponse(new Response(Response.Status.RPC_ERROR, e.toString()), null);
+      return new ShowCollectionInfoResponse(
+          new Response(Response.Status.RPC_ERROR, e.toString()), null);
+    }
+  }
+
+  @Override
+  public GetVectorByIdResponse getVectorById(String collectionName, Long id) {
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      return new GetVectorByIdResponse(
+          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;
+
+    try {
+      response = blockingStub.getVectorByID(request);
+
+      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+
+        logInfo(
+            "getVectorById for id={0} in collection `{1}` returned successfully!",
+            String.valueOf(id), collectionName);
+        return new GetVectorByIdResponse(
+            new Response(Response.Status.SUCCESS),
+            response.getVectorData().getFloatDataList(),
+            response.getVectorData().getBinaryData().asReadOnlyByteBuffer());
+      } else {
+        logSevere(
+            "getVectorById for `{0}` in collection `{1}` failed:\n{2}",
+            String.valueOf(id), collectionName, response.toString());
+        return new GetVectorByIdResponse(
+            new Response(
+                Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                response.getStatus().getReason()),
+            new ArrayList<>(),
+            null);
+      }
+    } catch (StatusRuntimeException e) {
+      logSevere("getVectorById RPC failed:\n{0}", e.getStatus().toString());
+      return new GetVectorByIdResponse(
+          new Response(Response.Status.RPC_ERROR, e.toString()), new ArrayList<>(), null);
+    }
+  }
+
+  @Override
+  public GetVectorIdsResponse getVectorIds(String collectionName, String segmentName) {
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      return new GetVectorIdsResponse(
+          new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
+    }
+
+    io.milvus.grpc.GetVectorIDsParam request =
+        io.milvus.grpc.GetVectorIDsParam.newBuilder()
+            .setTableName(collectionName)
+            .setSegmentName(segmentName)
+            .build();
+    io.milvus.grpc.VectorIds response;
+
+    try {
+      response = blockingStub.getVectorIDs(request);
+
+      if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+
+        logInfo(
+            "getVectorIds in collection `{0}`, segment `{1}` returned successfully!",
+            collectionName, segmentName);
+        return new GetVectorIdsResponse(
+            new Response(Response.Status.SUCCESS), response.getVectorIdArrayList());
+      } else {
+        logSevere(
+            "getVectorIds in collection `{0}`, segment `{1}` failed:\n{2}",
+            collectionName, segmentName, response.toString());
+        return new GetVectorIdsResponse(
+            new Response(
+                Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                response.getStatus().getReason()),
+            new ArrayList<>());
+      }
+    } catch (StatusRuntimeException e) {
+      logSevere("getVectorIds RPC failed:\n{0}", e.getStatus().toString());
+      return new GetVectorIdsResponse(
+          new Response(Response.Status.RPC_ERROR, e.toString()), new ArrayList<>());
+    }
+  }
+
+  @Override
+  public Response deleteByIds(String collectionName, List<Long> ids) {
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      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;
+
+    try {
+      response = blockingStub.deleteByID(request);
+
+      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+        logInfo("deleteByIds in collection `{0}` completed successfully!", collectionName);
+        return new Response(Response.Status.SUCCESS);
+      } else {
+        logSevere(
+            "deleteByIds in collection `{0}` failed:\n{1}", collectionName, response.toString());
+        return new Response(
+            Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
+      }
+    } catch (StatusRuntimeException e) {
+      logSevere("deleteByIds RPC failed:\n{0}", e.getStatus().toString());
+      return new Response(Response.Status.RPC_ERROR, e.toString());
     }
   }
 
   @Override
-  public Response dropIndex(@Nonnull String tableName) {
+  public Response deleteById(String collectionName, Long id) {
+    List<Long> list =
+        new ArrayList<Long>() {
+          {
+            add(id);
+          }
+        };
+    return deleteByIds(collectionName, list);
+  }
 
+  @Override
+  public Response flush(List<String> collectionNames) {
+    if (!channelIsReadyOrIdle()) {
+      logWarning("You are not connected to Milvus server");
+      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;
+
+    try {
+      response = blockingStub.flush(request);
+
+      if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
+        logInfo("Flushed collection {0} successfully!", collectionNames);
+        return new Response(Response.Status.SUCCESS);
+      } else {
+        logSevere("Flush collection {0} failed:\n{1}", collectionNames, response.toString());
+        return new Response(
+            Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
+      }
+    } catch (StatusRuntimeException e) {
+      logSevere("flush RPC failed:\n{0}", e.getStatus().toString());
+      return new Response(Response.Status.RPC_ERROR, e.toString());
+    }
+  }
+
+  @Override
+  public Response flush(String collectionName) {
+    List<String> list =
+        new ArrayList<String>() {
+          {
+            add(collectionName);
+          }
+        };
+    return flush(list);
+  }
+
+  @Override
+  public Response compact(String collectionName) {
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
       return new Response(Response.Status.CLIENT_NOT_CONNECTED);
     }
 
     io.milvus.grpc.TableName request =
-        io.milvus.grpc.TableName.newBuilder().setTableName(tableName).build();
+        io.milvus.grpc.TableName.newBuilder().setTableName(collectionName).build();
     io.milvus.grpc.Status response;
 
     try {
-      response = blockingStub.dropIndex(request);
+      response = blockingStub.compact(request);
 
       if (response.getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        logInfo("Dropped index for table `{0}` successfully!", tableName);
+        logInfo("Compacted collection `{0}` successfully!", collectionName);
         return new Response(Response.Status.SUCCESS);
       } else {
-        logSevere("Drop index for table `{0}` failed:\n{1}", tableName, response.toString());
+        logSevere("Compact collection `{0}` failed:\n{1}", collectionName, response.toString());
         return new Response(
             Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
       }
     } catch (StatusRuntimeException e) {
-      logSevere("dropIndex RPC failed:\n{0}", e.getStatus().toString());
+      logSevere("compact RPC failed:\n{0}", e.getStatus().toString());
       return new Response(Response.Status.RPC_ERROR, e.toString());
     }
   }
 
   ///////////////////// Util Functions/////////////////////
-  private List<io.milvus.grpc.RowRecord> getQueryRowRecordList(@Nonnull SearchParam searchParam) {
-    List<io.milvus.grpc.RowRecord> queryRowRecordList = new ArrayList<>();
-    for (List<Float> vectors : searchParam.getQueryVectors()) {
-      io.milvus.grpc.RowRecord rowRecord =
-          io.milvus.grpc.RowRecord.newBuilder().addAllVectorData(vectors).build();
-      queryRowRecordList.add(rowRecord);
-    }
-    return queryRowRecordList;
-  }
-
-  private List<io.milvus.grpc.Range> getQueryRangeList(@Nonnull SearchParam searchParam) {
-    List<io.milvus.grpc.Range> queryRangeList = new ArrayList<>();
-    String datePattern = "yyyy-MM-dd";
-    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
-    for (DateRange queryRange : searchParam.getDateRanges()) {
-      io.milvus.grpc.Range dateRange =
-          io.milvus.grpc.Range.newBuilder()
-              .setStartValue(simpleDateFormat.format(queryRange.getStartDate()))
-              .setEndValue(simpleDateFormat.format(queryRange.getEndDate()))
-              .build();
-      queryRangeList.add(dateRange);
+  private List<io.milvus.grpc.RowRecord> buildRowRecordList(
+      @Nonnull List<List<Float>> floatVectors, @Nonnull List<ByteBuffer> binaryVectors) {
+    List<io.milvus.grpc.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();
+
+      if (i < floatVectors.size()) {
+        rowRecordBuilder.addAllFloatData(floatVectors.get(i));
+      }
+      if (i < binaryVectors.size()) {
+        binaryVectors.get(i).rewind();
+        rowRecordBuilder.setBinaryData(ByteString.copyFrom(binaryVectors.get(i)));
+      }
+
+      rowRecordList.add(rowRecordBuilder.build());
     }
-    return queryRangeList;
-  }
 
-  private io.milvus.grpc.Range getRange(@Nonnull DateRange dateRange) {
-    String datePattern = "yyyy-MM-dd";
-    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
-    return io.milvus.grpc.Range.newBuilder()
-        .setStartValue(simpleDateFormat.format(dateRange.getStartDate()))
-        .setEndValue(simpleDateFormat.format(dateRange.getEndDate()))
-        .build();
+    return rowRecordList;
   }
 
   private SearchResponse buildSearchResponse(io.milvus.grpc.TopKQueryResult topKQueryResult) {

+ 0 - 80
src/main/java/io/milvus/client/Partition.java

@@ -1,80 +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.client;
-
-import javax.annotation.Nonnull;
-
-/** Represents a partition containing <code>tableName</code>, <code>partitionName</code> and <code>tag</code> */
-public class Partition {
-  private final String tableName;
-  private final String partitionName;
-  private final String tag;
-
-  private Partition(@Nonnull Builder builder) {
-    this.tableName = builder.tableName;
-    this.partitionName = builder.partitionName;
-    this.tag = builder.tag;
-  }
-
-  public String getTableName() {
-    return tableName;
-  }
-
-  public String getPartitionName() {
-    return partitionName;
-  }
-
-  public String getTag() {
-    return tag;
-  }
-
-  @Override
-  public String toString() {
-    return "Partition{"
-        + "tableName='"
-        + tableName
-        + '\''
-        + ", partitionName='"
-        + partitionName
-        + '\''
-        + ", tag='"
-        + tag
-        + '\''
-        + '}';
-  }
-
-  /** Builder for <code>Partition</code> */
-  public static class Builder {
-    // Required parameters
-    private final String tableName;
-    private final String partitionName;
-    private final String tag;
-
-    public Builder(@Nonnull String tableName, @Nonnull String partitionName, @Nonnull String tag) {
-      this.tableName = tableName;
-      this.partitionName = partitionName;
-      this.tag = tag;
-    }
-
-    public Partition build() {
-      return new Partition(this);
-    }
-  }
-}

+ 0 - 1
src/main/java/io/milvus/client/Response.java

@@ -71,7 +71,6 @@ public class Response {
     PERMISSION_DENIED(3),
     TABLE_NOT_EXISTS(4),
     ILLEGAL_ARGUMENT(5),
-    ILLEGAL_RANGE(6),
     ILLEGAL_DIMENSION(7),
     ILLEGAL_INDEX_TYPE(8),
     ILLEGAL_TABLE_NAME(9),

+ 0 - 62
src/main/java/io/milvus/client/SearchInFilesParam.java

@@ -1,62 +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.client;
-
-import javax.annotation.Nonnull;
-import java.util.List;
-
-/** Contains parameters for <code>searchInFiles</code> */
-public class SearchInFilesParam {
-  private final List<String> fileIds;
-  private final SearchParam searchParam;
-
-  private SearchInFilesParam(@Nonnull Builder builder) {
-    this.fileIds = builder.fileIds;
-    this.searchParam = builder.searchParam;
-  }
-
-  public List<String> getFileIds() {
-    return fileIds;
-  }
-
-  public SearchParam getSearchParam() {
-    return searchParam;
-  }
-
-  /** Builder for <code>SearchInFilesParam</code> */
-  public static class Builder {
-    // Required parameters
-    private final List<String> fileIds;
-    private final SearchParam searchParam;
-
-    /**
-     * @param fileIds a <code>List</code> of file ids to search from
-     * @param searchParam a <code>searchParam</code> object
-     */
-    public Builder(List<String> fileIds, SearchParam searchParam) {
-      this.fileIds = fileIds;
-      this.searchParam = searchParam;
-    }
-
-    public SearchInFilesParam build() {
-      return new SearchInFilesParam(this);
-    }
-  }
-}

+ 76 - 55
src/main/java/io/milvus/client/SearchParam.java

@@ -20,121 +20,142 @@
 package io.milvus.client;
 
 import javax.annotation.Nonnull;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 
 /** Contains parameters for <code>search</code> */
 public class SearchParam {
 
-  private final String tableName;
-  private final List<List<Float>> queryVectors;
-  private final List<DateRange> dateRanges;
-  private final long topK;
-  private final long nProbe;
+  private final String collectionName;
+  private final List<List<Float>> floatVectors;
+  private final List<ByteBuffer> binaryVectors;
   private final List<String> partitionTags;
+  private final long topK;
+  private final String paramsInJson;
 
   private SearchParam(@Nonnull Builder builder) {
-    this.tableName = builder.tableName;
-    this.queryVectors = builder.queryVectors;
-    this.dateRanges = builder.dateRanges;
-    this.nProbe = builder.nProbe;
-    this.topK = builder.topK;
+    this.collectionName = builder.collectionName;
+    this.floatVectors = builder.floatVectors;
+    this.binaryVectors = builder.binaryVectors;
     this.partitionTags = builder.partitionTags;
+    this.topK = builder.topK;
+    this.paramsInJson = builder.paramsInJson;
   }
 
-  public String getTableName() {
-    return tableName;
+  public String getCollectionName() {
+    return collectionName;
   }
 
-  public List<List<Float>> getQueryVectors() {
-    return queryVectors;
+  public List<List<Float>> getFloatVectors() {
+    return floatVectors;
   }
 
-  @Deprecated
-  public List<DateRange> getDateRanges() {
-    return dateRanges;
+  public List<ByteBuffer> getBinaryVectors() {
+    return binaryVectors;
   }
 
-  public long getTopK() {
-    return topK;
+  public List<String> getPartitionTags() {
+    return partitionTags;
   }
 
-  public long getNProbe() {
-    return nProbe;
+  public long getTopK() {
+    return topK;
   }
 
-  public List<String> getPartitionTags() {
-    return partitionTags;
+  public String getParamsInJson() {
+    return paramsInJson;
   }
 
   /** Builder for <code>SearchParam</code> */
   public static class Builder {
     // Required parameters
-    private final String tableName;
-    private final List<List<Float>> queryVectors;
+    private final String collectionName;
 
     // Optional parameters - initialized to default values
-    private List<DateRange> dateRanges = new ArrayList<>();
-    private long topK = 1024;
-    private long nProbe = 20;
+    private List<List<Float>> floatVectors = new ArrayList<>();
+    private List<ByteBuffer> binaryVectors = new ArrayList<>();
     private List<String> partitionTags = new ArrayList<>();
+    private long topK = 1024;
+    private String paramsInJson;
+
+    /** @param collectionName collection to search from */
+    public Builder(@Nonnull String collectionName) {
+      this.collectionName = collectionName;
+    }
 
     /**
-     * @param tableName table to search from
-     * @param queryVectors a <code>List</code> of vectors to be queried. Each inner <code>List
-     *     </code> represents a vector.
+     * Default to an empty <code>ArrayList</code>. You can search either float or binary vectors,
+     * not both.
+     *
+     * @param floatVectors a <code>List</code> of float vectors to be queries. Each inner <code>List
+     *     </code> represents a float vector.
+     * @return <code>Builder</code>
      */
-    public Builder(@Nonnull String tableName, @Nonnull List<List<Float>> queryVectors) {
-      this.tableName = tableName;
-      this.queryVectors = queryVectors;
+    public SearchParam.Builder withFloatVectors(@Nonnull List<List<Float>> floatVectors) {
+      this.floatVectors = floatVectors;
+      return this;
     }
 
     /**
-     * Deprecated. Optional. Searches vectors in their corresponding date range. Default to an empty
-     * <code>
-     * ArrayList</code>
+     * Default to an empty <code>ArrayList</code>. You can search either float or binary vectors,
+     * not both.
      *
-     * @param dateRanges a <code>List</code> of <code>DateRange</code> objects
+     * @param binaryVectors a <code>List</code> of binary vectors to be queried. Each <code>
+     *     ByteBuffer</code> object represents a binary vector, with every 8 bits constituting a
+     *     byte.
      * @return <code>Builder</code>
-     * @see DateRange
+     * @see ByteBuffer
      */
-    @Deprecated
-    public Builder withDateRanges(@Nonnull List<DateRange> dateRanges) {
-      this.dateRanges = dateRanges;
+    public SearchParam.Builder withBinaryVectors(@Nonnull List<ByteBuffer> binaryVectors) {
+      this.binaryVectors = binaryVectors;
       return this;
     }
 
     /**
-     * Optional. Limits search result to <code>topK</code>. Default to 1024.
+     * Optional. Search vectors with corresponding <code>partitionTags</code>. Default to an empty
+     * <code>List</code>
      *
-     * @param topK a topK number
+     * @param partitionTags a <code>List</code> of partition tags
      * @return <code>Builder</code>
      */
-    public Builder withTopK(long topK) {
-      this.topK = topK;
+    public Builder withPartitionTags(@Nonnull List<String> partitionTags) {
+      this.partitionTags = partitionTags;
       return this;
     }
 
     /**
-     * Optional. Default to 20.
+     * Optional. Limits search result to <code>topK</code>. Default to 1024.
      *
-     * @param nProbe a nProbe number
+     * @param topK a topK number
      * @return <code>Builder</code>
      */
-    public Builder withNProbe(long nProbe) {
-      this.nProbe = nProbe;
+    public Builder withTopK(long topK) {
+      this.topK = topK;
       return this;
     }
 
     /**
-     * Optional. Search vectors with corresponding <code>partitionTags</code>. Default to an empty
-     * <code>List</code>
+     * Optional. Default to empty <code>String</code>.
      *
-     * @param partitionTags a <code>List</code> of partition tags
+     * <pre>
+     *   For different index type, search parameter is different accordingly, for example:
+     *
+     *   FLAT/IVFLAT/SQ8/IVFPQ: {"nprobe": 32}
+     *   nprobe range:[1,999999]
+     *
+     *   NSG: {"search_length": 100}
+     *   search_length range:[10, 300]
+     *
+     *   HNSW: {"ef": 64}
+     *   ef range:[topk, 4096]
+     * </pre>
+     *
+     * @param paramsInJson extra parameters in JSON format
      * @return <code>Builder</code>
      */
-    public Builder withPartitionTags(List<String> partitionTags) {
-      this.partitionTags = partitionTags;
+    public SearchParam.Builder withParamsInJson(@Nonnull String paramsInJson) {
+      this.paramsInJson = paramsInJson;
       return this;
     }
 

+ 1 - 0
src/main/java/io/milvus/client/SearchResponse.java

@@ -102,6 +102,7 @@ public class SearchResponse {
     this.response = response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }

+ 36 - 0
src/main/java/io/milvus/client/ShowCollectionInfoResponse.java

@@ -0,0 +1,36 @@
+package io.milvus.client;
+
+import java.util.Optional;
+
+/**
+ * Contains the returned <code>response</code> and <code>collectionInfo</code> for <code>
+ * showCollectionInfo</code>
+ */
+public class ShowCollectionInfoResponse {
+
+  private final Response response;
+  private final CollectionInfo collectionInfo;
+
+  ShowCollectionInfoResponse(Response response, CollectionInfo collectionInfo) {
+    this.response = response;
+    this.collectionInfo = collectionInfo;
+  }
+
+  public Response getResponse() {
+    return response;
+  }
+
+  /**
+   * @return an <code>Optional</code> object which may or may not contain an <code>CollectionInfo
+   *     </code> object
+   * @see Optional
+   */
+  public Optional<CollectionInfo> getCollectionInfo() {
+    return Optional.ofNullable(collectionInfo);
+  }
+
+  /** @return <code>true</code> if the response status equals SUCCESS */
+  public boolean ok() {
+    return response.ok();
+  }
+}

+ 11 - 8
src/main/java/io/milvus/client/ShowTablesResponse.java → src/main/java/io/milvus/client/ShowCollectionsResponse.java

@@ -22,26 +22,28 @@ package io.milvus.client;
 import java.util.List;
 
 /**
- * Contains the returned <code>response</code> and <code>tableNames</code> for <code>showTables
+ * Contains the returned <code>response</code> and <code>collectionNames</code> for <code>
+ * showCollections
  * </code>
  */
-public class ShowTablesResponse {
+public class ShowCollectionsResponse {
   private final Response response;
-  private final List<String> tableNames;
+  private final List<String> collectionNames;
 
-  ShowTablesResponse(Response response, List<String> tableNames) {
+  ShowCollectionsResponse(Response response, List<String> collectionNames) {
     this.response = response;
-    this.tableNames = tableNames;
+    this.collectionNames = collectionNames;
   }
 
-  public List<String> getTableNames() {
-    return tableNames;
+  public List<String> getCollectionNames() {
+    return collectionNames;
   }
 
   public Response getResponse() {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }
@@ -49,6 +51,7 @@ public class ShowTablesResponse {
   @Override
   public String toString() {
     return String.format(
-        "ShowTablesResponse {%s, table names = %s}", response, tableNames.toString());
+        "ShowCollectionsResponse {%s, collection names = %s}",
+        response, collectionNames.toString());
   }
 }

+ 7 - 41
src/main/java/io/milvus/client/ShowPartitionsResponse.java

@@ -19,66 +19,32 @@
 
 package io.milvus.client;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Contains the returned <code>response</code> and <code>partitionList</code> for <code>showPartitions
+ * Contains the returned <code>response</code> and <code>partitionList</code> for <code>
+ * showPartitions
  * </code>
  */
 public class ShowPartitionsResponse {
   private final Response response;
-  private final List<Partition> partitionList;
+  private final List<String> partitionList;
 
-  ShowPartitionsResponse(Response response, List<Partition> partitionList) {
+  ShowPartitionsResponse(Response response, List<String> partitionList) {
     this.response = response;
     this.partitionList = partitionList;
   }
 
-  /**
-   * @return a <code>List</code> of <code>Partition</code>s.
-   */
-  public List<Partition> getPartitionList() {
+  /** @return a <code>List</code> of partition tags. */
+  public List<String> getPartitionList() {
     return partitionList;
   }
 
-  /**
-   * @return a <code>List</code> of table names of each partition.
-   */
-  public List<String> getTableNameList() {
-    List<String> tableNameList = new ArrayList<>();
-    for (Partition partition : partitionList) {
-      tableNameList.add(partition.getTableName());
-    }
-    return tableNameList;
-  }
-
-  /**
-   * @return a <code>List</code> of partition names.
-   */
-  public List<String> getPartitionNameList() {
-    List<String> partitionNameList = new ArrayList<>();
-    for (Partition partition : partitionList) {
-      partitionNameList.add(partition.getPartitionName());
-    }
-    return partitionNameList;
-  }
-
-  /**
-   * @return a <code>List</code> of partition tags.
-   */
-  public List<String> getPartitionTagList() {
-    List<String> partitionTagList = new ArrayList<>();
-    for (Partition partition : partitionList) {
-      partitionTagList.add(partition.getTag());
-    }
-    return partitionTagList;
-  }
-
   public Response getResponse() {
     return response;
   }
 
+  /** @return <code>true</code> if the response status equals SUCCESS */
   public boolean ok() {
     return response.ok();
   }

+ 219 - 387
src/main/proto/milvus.proto

@@ -9,606 +9,438 @@ option java_outer_classname = "MilvusProto";
 package milvus.grpc;
 
 /**
-
- * @brief Table Name
-
+ * @brief general usage
  */
-
-message TableName {
-
-    string table_name = 1;
-
+message KeyValuePair {
+    string key = 1;
+    string value = 2;
 }
 
 /**
-
- * @brief Partition name
-
+ * @brief Table name
  */
-
-message PartitionName {
-    string partition_name = 1;
+message TableName {
+    string table_name = 1;
 }
 
 /**
-
- * @brief Table Name List
-
+ * @brief Table name list
  */
-
 message TableNameList {
-
     Status status = 1;
-
     repeated string table_names = 2;
-
 }
 
 /**
-
- * @brief Table Schema
-
+ * @brief Table schema
+ * metric_type: 1-L2, 2-IP
  */
-
 message TableSchema {
-
     Status status = 1;
-
     string table_name = 2;
-
     int64 dimension = 3;
-
     int64 index_file_size = 4;
-
     int32 metric_type = 5;
-
-}
-
-/**
-
- * @brief Range Schema
-
- */
-
-message Range {
-
-    string start_value = 1;
-
-    string end_value = 2;
-
+    repeated KeyValuePair extra_params = 6;
 }
 
 /**
-
- * @brief Record inserted
-
+ * @brief Params of partition
  */
-
-message RowRecord {
-
-    repeated float vector_data = 1; //binary vector data
-
-}
-
-/**
-
- * @brief Partition param
-
- */
-
 message PartitionParam {
     string table_name = 1;
-    string partition_name = 2;
-    string tag = 3;
+    string tag = 2;
 }
 
 /**
-
  * @brief Partition list
-
  */
-
 message PartitionList {
     Status status = 1;
-    repeated PartitionParam partition_array = 2;
+    repeated string partition_tag_array = 2;
 }
 
 /**
-
- * @brief params to be inserted
-
+ * @brief Record inserted
  */
+message RowRecord {
+    repeated float float_data = 1;             //float vector data
+    bytes binary_data = 2;                      //binary vector data
+}
 
+/**
+ * @brief Params to be inserted
+ */
 message InsertParam {
-
     string table_name = 1;
-
     repeated RowRecord row_record_array = 2;
-
-    repeated int64 row_id_array = 3; //optional
-
-    string partition_tag = 4; // default empty
-
+    repeated int64 row_id_array = 3;            //optional
+    string partition_tag = 4;
+    repeated KeyValuePair extra_params = 5;
 }
 
 /**
-
  * @brief Vector ids
-
  */
-
 message VectorIds {
-
     Status status = 1;
-
     repeated int64 vector_id_array = 2;
-
 }
 
 /**
-
- * @brief params for searching vector
-
+ * @brief Params for searching vector
  */
-
 message SearchParam {
-
     string table_name = 1;
-
-    repeated RowRecord query_record_array = 2;
-
-    repeated Range query_range_array = 3;
-
+    repeated string partition_tag_array = 2;
+    repeated RowRecord query_record_array = 3;
     int64 topk = 4;
-
-    int64 nprobe = 5;
-
-    repeated string partition_tag_array = 6; // default empty
-
+    repeated KeyValuePair extra_params = 5;
 }
 
 /**
-
- * @brief params for searching vector in files
-
+ * @brief Params for searching vector in files
  */
-
 message SearchInFilesParam {
-
     repeated string file_id_array = 1;
-
     SearchParam search_param = 2;
-
 }
 
 /**
+ * @brief Params for searching vector by ID
+ */
+message SearchByIDParam {
+    string table_name = 1;
+    repeated string partition_tag_array = 2;
+    int64 id = 3;
+    int64 topk = 4;
+    repeated KeyValuePair extra_params = 5;
+}
 
+/**
  * @brief Query result params
-
  */
-
 message TopKQueryResult {
-
     Status status = 1;
-
     int64 row_num = 2;
-
     repeated int64 ids = 3;
-
     repeated float distances = 4;
-
 }
 
 /**
-
- * @brief Server String Reply
-
+ * @brief Server string Reply
  */
-
 message StringReply {
-
     Status status = 1;
-
     string string_reply = 2;
-
 }
 
 /**
-
  * @brief Server bool Reply
-
  */
-
 message BoolReply {
-
     Status status = 1;
-
     bool bool_reply = 2;
-
 }
 
 /**
-
  * @brief Return table row count
-
  */
-
 message TableRowCount {
-
     Status status = 1;
-
     int64 table_row_count = 2;
-
 }
 
 /**
-
- * @brief Give Server Command
-
+ * @brief Give server Command
  */
-
 message Command {
-
     string cmd = 1;
-
 }
 
 /**
-
- * @brief Index
-
+ * @brief Index params
  * @index_type: 0-invalid, 1-idmap, 2-ivflat, 3-ivfsq8, 4-nsgmix
-
- * @metric_type: 1-L2, 2-IP
-
  */
-
-message Index {
-
-    int32 index_type = 1;
-
-    int32 nlist = 2;
-
+message IndexParam {
+    Status status = 1;
+    string table_name = 2;
+    int32 index_type = 3;
+    repeated KeyValuePair extra_params = 4;
 }
 
 /**
+ * @brief Flush params
+ */
+message FlushParam {
+    repeated string table_name_array = 1;
+}
 
- * @brief Index params
+/**
+ * @brief Flush params
+ */
+message DeleteByIDParam {
+    string table_name = 1;
+    repeated int64 id_array = 2;
+}
 
+/**
+ * @brief segment statistics
  */
+message SegmentStat {
+    string segment_name = 1;
+    int64 row_count = 2;
+    string index_name = 3;
+    int64 data_size = 4;
+}
 
-message IndexParam {
+/**
+ * @brief table statistics
+ */
+message PartitionStat {
+    string tag = 1;
+    int64 total_row_count = 2;
+    repeated SegmentStat segments_stat = 3;
+}
 
+/**
+ * @brief table information
+ */
+message TableInfo {
     Status status = 1;
-
-    string table_name = 2;
-
-    Index index = 3;
-
+    int64 total_row_count = 2;
+    repeated PartitionStat partitions_stat = 3;
 }
 
 /**
-
- * @brief table name and range for DeleteByRange
-
+ * @brief vector identity
  */
+message VectorIdentity {
+    string table_name = 1;
+    int64 id = 2;
+}
 
-message DeleteByRangeParam {
-
-    Range range = 1;
-
-    string table_name = 2;
+/**
+ * @brief vector data
+ */
+message VectorData {
+    Status status = 1;
+    RowRecord vector_data = 2;
+}
 
+/**
+ * @brief get vector ids from a segment parameters
+ */
+message GetVectorIDsParam {
+    string table_name = 1;
+    string segment_name = 2;
 }
 
 service MilvusService {
-
     /**
-
-     * @brief Create table method
-
+     * @brief This method is used to create table
      *
-
-     * This method is used to create table
-
-     *
-
-     * @param param, use to provide table information to be created.
-
+     * @param TableSchema, use to provide table information to be created.
      *
-
+     * @return Status
      */
-
-    rpc CreateTable (TableSchema) returns (Status) {
-    }
+    rpc CreateTable(TableSchema) returns (Status){}
 
     /**
-
-     * @brief Test table existence method
-
-     *
-
-     * This method is used to test table existence.
-
+     * @brief This method is used to test table existence.
      *
-
-     * @param table_name, table name is going to be tested.
-
+     * @param TableName, table name is going to be tested.
      *
-
+     * @return BoolReply
      */
-
-    rpc HasTable (TableName) returns (BoolReply) {
-    }
+    rpc HasTable(TableName) returns (BoolReply) {}
 
     /**
-
-     * @brief Delete table method
-
+     * @brief This method is used to get table schema.
      *
-
-     * This method is used to delete table.
-
+     * @param TableName, target table name.
      *
+     * @return TableSchema
+     */
+    rpc DescribeTable(TableName) returns (TableSchema) {}
 
-     * @param table_name, table name is going to be deleted.
-
+    /**
+     * @brief This method is used to get table schema.
      *
-
+     * @param TableName, target table name.
+     *
+     * @return TableRowCount
      */
-
-    rpc DropTable (TableName) returns (Status) {
-    }
+    rpc CountTable(TableName) returns (TableRowCount) {}
 
     /**
-
-     * @brief Build index by table method
-
+     * @brief This method is used to list all tables.
      *
-
-     * This method is used to build index by table in sync mode.
-
+     * @param Command, dummy parameter.
      *
+     * @return TableNameList
+     */
+    rpc ShowTables(Command) returns (TableNameList) {}
 
-     * @param table_name, table is going to be built index.
-
+    /**
+     * @brief This method is used to get table detail information.
      *
-
+     * @param TableName, target table name.
+     *
+     * @return TableInfo
      */
-
-    rpc CreateIndex (IndexParam) returns (Status) {
-    }
-
-    rpc CreatePartition (PartitionParam) returns (Status) {
-    }
-
-    rpc ShowPartitions (TableName) returns (PartitionList) {
-    }
-
-    rpc DropPartition (PartitionParam) returns (Status) {
-    }
+    rpc ShowTableInfo(TableName) returns (TableInfo) {}
 
     /**
-
-     * @brief Add vector array to table
-
+     * @brief This method is used to delete table.
      *
-
-     * This method is used to add vector array to table.
-
+     * @param TableName, table name is going to be deleted.
      *
+     * @return TableNameList
+     */
+    rpc DropTable(TableName) returns (Status) {}
 
-     * @param table_name, table_name is inserted.
-
-     * @param record_array, vector array is inserted.
-
+    /**
+     * @brief This method is used to build index by table in sync mode.
      *
-
-     * @return vector id array
-
+     * @param IndexParam, index paramters.
+     *
+     * @return Status
      */
-
-    rpc Insert (InsertParam) returns (VectorIds) {
-    }
+    rpc CreateIndex(IndexParam) returns (Status) {}
 
     /**
-
-     * @brief Query vector
-
+     * @brief This method is used to describe index
      *
-
-     * This method is used to query vector in table.
-
+     * @param TableName, target table name.
      *
+     * @return IndexParam
+     */
+    rpc DescribeIndex(TableName) returns (IndexParam) {}
 
-     * @param table_name, table_name is queried.
-
-     * @param query_record_array, all vector are going to be queried.
-
-     * @param query_range_array, optional ranges for conditional search. If not specified, search whole table
-
-     * @param topk, how many similarity vectors will be searched.
-
+    /**
+     * @brief This method is used to drop index
      *
-
-     * @return query result array.
-
+     * @param TableName, target table name.
+     *
+     * @return Status
      */
-
-    rpc Search (SearchParam) returns (TopKQueryResult) {
-    }
+    rpc DropIndex(TableName) returns (Status) {}
 
     /**
-
-     * @brief Internal use query interface
-
+     * @brief This method is used to create partition
      *
-
-     * This method is used to query vector in specified files.
-
+     * @param PartitionParam, partition parameters.
      *
+     * @return Status
+     */
+    rpc CreatePartition(PartitionParam) returns (Status) {}
 
-     * @param file_id_array, specified files id array, queried.
-
-     * @param query_record_array, all vector are going to be queried.
-
-     * @param query_range_array, optional ranges for conditional search. If not specified, search whole table
-
-     * @param topk, how many similarity vectors will be searched.
-
+    /**
+     * @brief This method is used to show partition information
      *
-
-     * @return query result array.
-
+     * @param TableName, target table name.
+     *
+     * @return PartitionList
      */
-
-    rpc SearchInFiles (SearchInFilesParam) returns (TopKQueryResult) {
-    }
+    rpc ShowPartitions(TableName) returns (PartitionList) {}
 
     /**
-
-     * @brief Get table schema
-
+     * @brief This method is used to drop partition
      *
-
-     * This method is used to get table schema.
-
+     * @param PartitionParam, target partition.
      *
+     * @return Status
+     */
+    rpc DropPartition(PartitionParam) returns (Status) {}
 
-     * @param table_name, target table name.
-
+    /**
+     * @brief This method is used to add vector array to table.
      *
-
-     * @return table schema
-
+     * @param InsertParam, insert parameters.
+     *
+     * @return VectorIds
      */
-
-    rpc DescribeTable (TableName) returns (TableSchema) {
-    }
+    rpc Insert(InsertParam) returns (VectorIds) {}
 
     /**
-
-     * @brief Get table schema
-
+     * @brief This method is used to get vector data by id.
      *
-
-     * This method is used to get table schema.
-
+     * @param VectorIdentity, target vector id.
      *
+     * @return VectorData
+     */
+    rpc GetVectorByID(VectorIdentity) returns (VectorData) {}
 
-     * @param table_name, target table name.
-
+    /**
+     * @brief This method is used to get vector ids from a segment
      *
-
-     * @return table schema
-
+     * @param GetVectorIDsParam, target table and segment
+     *
+     * @return VectorIds
      */
-
-    rpc CountTable (TableName) returns (TableRowCount) {
-    }
+    rpc GetVectorIDs(GetVectorIDsParam) returns (VectorIds) {}
 
     /**
-
-     * @brief List all tables in database
-
+     * @brief This method is used to query vector in table.
      *
-
-     * This method is used to list all tables.
-
+     * @param SearchParam, search parameters.
      *
+     * @return TopKQueryResult
+     */
+    rpc Search(SearchParam) returns (TopKQueryResult) {}
 
+    /**
+     * @brief This method is used to query vector in specified files.
      *
-
-     * @return table names.
-
+     * @param SearchInFilesParam, search in files paremeters.
+     *
+     * @return TopKQueryResult
      */
-
-    rpc ShowTables (Command) returns (TableNameList) {
-    }
+    rpc SearchInFiles(SearchInFilesParam) returns (TopKQueryResult) {}
 
     /**
-
-     * @brief Give the server status
-
+     * @brief This method is used to give the server status.
      *
-
-     * This method is used to give the server status.
-
+     * @param Command, command string
      *
-
-     * @return Server status.
-
+     * @return StringReply
      */
-
-    rpc Cmd (Command) returns (StringReply) {
-    }
+    rpc Cmd(Command) returns (StringReply) {}
 
     /**
-
-    * @brief delete table by range
-
-    *
-
-    * This method is used to delete vector by range
-
-    *
-
-    * @return rpc status.
-
-    */
-
-    rpc DeleteByRange (DeleteByRangeParam) returns (Status) {
-    }
+     * @brief This method is used to delete vector by id
+     *
+     * @param DeleteByIDParam, delete parameters.
+     *
+     * @return status
+     */
+    rpc DeleteByID(DeleteByIDParam) returns (Status) {}
 
     /**
-
-     * @brief preload table
-
+     * @brief This method is used to preload table
      *
-
-     * This method is used to preload table
-
+     * @param TableName, target table name.
      *
-
-     * @return Status.
-
+     * @return Status
      */
-
-    rpc PreloadTable (TableName) returns (Status) {
-    }
+    rpc PreloadTable(TableName) returns (Status) {}
 
     /**
-
-     * @brief describe index
-
+     * @brief This method is used to flush buffer into storage.
      *
-
-     * This method is used to describe index
-
+     * @param FlushParam, flush parameters
      *
-
-     * @return Status.
-
+     * @return Status
      */
-
-    rpc DescribeIndex (TableName) returns (IndexParam) {
-    }
+    rpc Flush(FlushParam) returns (Status) {}
 
     /**
-
-     * @brief drop index
-
+     * @brief This method is used to compact table
      *
-
-     * This method is used to drop index
-
+     * @param TableName, target table name.
      *
-
-     * @return Status.
-
+     * @return Status
      */
-
-    rpc DropIndex (TableName) returns (Status) {
-    }
-
+    rpc Compact(TableName) returns (Status) {}
 }

+ 0 - 1
src/main/proto/status.proto

@@ -13,7 +13,6 @@ enum ErrorCode {
     PERMISSION_DENIED = 3;
     TABLE_NOT_EXISTS = 4;
     ILLEGAL_ARGUMENT = 5;
-    ILLEGAL_RANGE = 6;
     ILLEGAL_DIMENSION = 7;
     ILLEGAL_INDEX_TYPE = 8;
     ILLEGAL_TABLE_NAME = 9;

+ 348 - 94
src/test/java/io/milvus/client/MilvusGrpcClientTest.java

@@ -21,6 +21,7 @@ package io.milvus.client;
 
 import org.apache.commons.text.RandomStringGenerator;
 
+import java.nio.ByteBuffer;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -35,15 +36,15 @@ class MilvusClientTest {
 
   private RandomStringGenerator generator;
 
-  private String randomTableName;
+  private String randomCollectionName;
   private long size;
   private long dimension;
 
-  // Helper function that generates random vectors
-  static List<List<Float>> generateVectors(long vectorCount, long dimension) {
+  // Helper function that generates random float vectors
+  static List<List<Float>> generateFloatVectors(long vectorCount, long dimension) {
     SplittableRandom splittableRandom = new SplittableRandom();
     List<List<Float>> vectors = new ArrayList<>();
-    for (int i = 0; i < vectorCount; ++i) {
+    for (long i = 0; i < vectorCount; ++i) {
       splittableRandom = splittableRandom.split();
       DoubleStream doubleStream = splittableRandom.doubles(dimension);
       List<Float> vector =
@@ -53,6 +54,19 @@ class MilvusClientTest {
     return vectors;
   }
 
+  // Helper function that generates random binary vectors
+  static List<ByteBuffer> generateBinaryVectors(long vectorCount, long dimension) {
+    Random random = new Random();
+    List<ByteBuffer> vectors = new ArrayList<>();
+    final long dimensionInByte = dimension / 8;
+    for (long i = 0; i < vectorCount; ++i) {
+      ByteBuffer byteBuffer = ByteBuffer.allocate((int) dimensionInByte);
+      random.nextBytes(byteBuffer.array());
+      vectors.add(byteBuffer);
+    }
+    return vectors;
+  }
+
   // Helper function that normalizes a vector if you are using IP (Inner Product) as your metric
   // type
   static List<Float> normalizeVector(List<Float> vector) {
@@ -67,25 +81,25 @@ class MilvusClientTest {
 
     client = new MilvusGrpcClient();
     ConnectParam connectParam =
-        new ConnectParam.Builder().withHost("localhost").withPort("19530").build();
+        new ConnectParam.Builder().withHost("localhost").withPort(19530).build();
     client.connect(connectParam);
 
     generator = new RandomStringGenerator.Builder().withinRange('a', 'z').build();
-    randomTableName = generator.generate(10);
+    randomCollectionName = generator.generate(10);
     size = 100000;
     dimension = 128;
-    TableSchema tableSchema =
-        new TableSchema.Builder(randomTableName, dimension)
+    CollectionMapping collectionMapping =
+        new CollectionMapping.Builder(randomCollectionName, dimension)
             .withIndexFileSize(1024)
             .withMetricType(MetricType.IP)
             .build();
 
-    assertTrue(client.createTable(tableSchema).ok());
+    assertTrue(client.createCollection(collectionMapping).ok());
   }
 
   @org.junit.jupiter.api.AfterEach
   void tearDown() throws InterruptedException {
-    assertTrue(client.dropTable(randomTableName).ok());
+    assertTrue(client.dropCollection(randomCollectionName).ok());
     client.disconnect();
   }
 
@@ -102,7 +116,7 @@ class MilvusClientTest {
     // Channel should be idle
     assertFalse(client.isConnected());
     // A new RPC would take the channel out of idle mode
-    assertTrue(client.showTables().ok());
+    assertTrue(client.showCollections().ok());
   }
 
   @org.junit.jupiter.api.Test
@@ -110,7 +124,7 @@ class MilvusClientTest {
     assertThrows(
         IllegalArgumentException.class,
         () -> {
-          ConnectParam connectParam = new ConnectParam.Builder().withPort("66666").build();
+          ConnectParam connectParam = new ConnectParam.Builder().withPort(66666).build();
         });
     assertThrows(
         IllegalArgumentException.class,
@@ -151,70 +165,69 @@ class MilvusClientTest {
   }
 
   @org.junit.jupiter.api.Test
-  void createInvalidTable() {
-    String invalidTableName = "╯°□°)╯";
-    TableSchema invalidTableSchema = new TableSchema.Builder(invalidTableName, dimension).build();
-    Response createTableResponse = client.createTable(invalidTableSchema);
-    assertFalse(createTableResponse.ok());
-    assertEquals(Response.Status.ILLEGAL_TABLE_NAME, createTableResponse.getStatus());
+  void createInvalidCollection() {
+    String invalidCollectionName = "╯°□°)╯";
+    CollectionMapping invalidCollectionMapping =
+        new CollectionMapping.Builder(invalidCollectionName, dimension).build();
+    Response createCollectionResponse = client.createCollection(invalidCollectionMapping);
+    assertFalse(createCollectionResponse.ok());
+    assertEquals(Response.Status.ILLEGAL_TABLE_NAME, createCollectionResponse.getStatus());
   }
 
   @org.junit.jupiter.api.Test
-  void hasTable() {
-    HasTableResponse hasTableResponse = client.hasTable(randomTableName);
-    assertTrue(hasTableResponse.ok());
+  void hasCollection() {
+    HasCollectionResponse hasCollectionResponse = client.hasCollection(randomCollectionName);
+    assertTrue(hasCollectionResponse.ok());
+    assertTrue(hasCollectionResponse.hasCollection());
   }
 
   @org.junit.jupiter.api.Test
-  void dropTable() {
-    String nonExistingTableName = generator.generate(10);
-    Response dropTableResponse = client.dropTable(nonExistingTableName);
-    assertFalse(dropTableResponse.ok());
-    assertEquals(Response.Status.TABLE_NOT_EXISTS, dropTableResponse.getStatus());
+  void dropCollection() {
+    String nonExistingCollectionName = generator.generate(10);
+    Response dropCollectionResponse = client.dropCollection(nonExistingCollectionName);
+    assertFalse(dropCollectionResponse.ok());
+    assertEquals(Response.Status.TABLE_NOT_EXISTS, dropCollectionResponse.getStatus());
   }
 
   @org.junit.jupiter.api.Test
-  void partitionTest() throws InterruptedException {
-    final String partitionName1 = "partition1";
+  void partitionTest() {
     final String tag1 = "tag1";
-
-    Partition partition = new Partition.Builder(randomTableName, partitionName1, tag1).build();
-    Response createPartitionResponse = client.createPartition(partition);
+    Response createPartitionResponse = client.createPartition(randomCollectionName, tag1);
     assertTrue(createPartitionResponse.ok());
 
-    final String partitionName2 = "partition2";
     final String tag2 = "tag2";
-
-    Partition partition2 = new Partition.Builder(randomTableName, partitionName2, tag2).build();
-    createPartitionResponse = client.createPartition(partition2);
+    createPartitionResponse = client.createPartition(randomCollectionName, tag2);
     assertTrue(createPartitionResponse.ok());
 
-    ShowPartitionsResponse showPartitionsResponse = client.showPartitions(randomTableName);
+    ShowPartitionsResponse showPartitionsResponse = client.showPartitions(randomCollectionName);
     assertTrue(showPartitionsResponse.ok());
-    assertEquals(2, showPartitionsResponse.getPartitionList().size());
+    assertEquals(3, showPartitionsResponse.getPartitionList().size()); // two tags plus _default
 
-    List<List<Float>> vectors1 = generateVectors(size, dimension);
+    List<List<Float>> vectors1 = generateFloatVectors(size, dimension);
     List<Long> vectorIds1 = LongStream.range(0, size).boxed().collect(Collectors.toList());
     InsertParam insertParam =
-        new InsertParam.Builder(randomTableName, vectors1)
+        new InsertParam.Builder(randomCollectionName)
+            .withFloatVectors(vectors1)
             .withVectorIds(vectorIds1)
             .withPartitionTag(tag1)
             .build();
     InsertResponse insertResponse = client.insert(insertParam);
     assertTrue(insertResponse.ok());
-    List<List<Float>> vectors2 = generateVectors(size, dimension);
+    List<List<Float>> vectors2 = generateFloatVectors(size, dimension);
     List<Long> vectorIds2 = LongStream.range(size, size * 2).boxed().collect(Collectors.toList());
     insertParam =
-        new InsertParam.Builder(randomTableName, vectors2)
+        new InsertParam.Builder(randomCollectionName)
+            .withFloatVectors(vectors2)
             .withVectorIds(vectorIds2)
             .withPartitionTag(tag2)
             .build();
     insertResponse = client.insert(insertParam);
     assertTrue(insertResponse.ok());
 
-    TimeUnit.SECONDS.sleep(1);
+    assertTrue(client.flush(randomCollectionName).ok());
 
-    assertEquals(size * 2, client.getTableRowCount(randomTableName).getTableRowCount());
+    assertEquals(
+        size * 2, client.getCollectionRowCount(randomCollectionName).getCollectionRowCount());
 
     final int searchSize = 1;
     final long topK = 10;
@@ -223,10 +236,11 @@ class MilvusClientTest {
     List<String> partitionTags1 = new ArrayList<>();
     partitionTags1.add(tag1);
     SearchParam searchParam1 =
-        new SearchParam.Builder(randomTableName, vectorsToSearch1)
+        new SearchParam.Builder(randomCollectionName)
+            .withFloatVectors(vectorsToSearch1)
             .withTopK(topK)
-            .withNProbe(20)
             .withPartitionTags(partitionTags1)
+            .withParamsInJson("{\"nprobe\": 20}")
             .build();
     SearchResponse searchResponse1 = client.search(searchParam1);
     assertTrue(searchResponse1.ok());
@@ -238,10 +252,11 @@ class MilvusClientTest {
     List<String> partitionTags2 = new ArrayList<>();
     partitionTags2.add(tag2);
     SearchParam searchParam2 =
-        new SearchParam.Builder(randomTableName, vectorsToSearch2)
+        new SearchParam.Builder(randomCollectionName)
+            .withFloatVectors(vectorsToSearch2)
             .withTopK(topK)
-            .withNProbe(20)
             .withPartitionTags(partitionTags2)
+            .withParamsInJson("{\"nprobe\": 20}")
             .build();
     SearchResponse searchResponse2 = client.search(searchParam2);
     assertTrue(searchResponse2.ok());
@@ -251,62 +266,82 @@ class MilvusClientTest {
 
     assertTrue(Collections.disjoint(resultIdsList1, resultIdsList2));
 
-    Response dropPartitionResponse = client.dropPartition(partitionName1);
+    Response dropPartitionResponse = client.dropPartition(randomCollectionName, tag1);
     assertTrue(dropPartitionResponse.ok());
 
-    dropPartitionResponse = client.dropPartition(randomTableName, tag2);
+    dropPartitionResponse = client.dropPartition(randomCollectionName, tag2);
     assertTrue(dropPartitionResponse.ok());
   }
 
   @org.junit.jupiter.api.Test
   void createIndex() {
-    Index index = new Index.Builder().withIndexType(IndexType.IVF_SQ8).withNList(16384).build();
-    CreateIndexParam createIndexParam =
-        new CreateIndexParam.Builder(randomTableName).withIndex(index).build();
-    Response createIndexResponse = client.createIndex(createIndexParam);
+    insert();
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    Index index =
+        new Index.Builder(randomCollectionName, IndexType.IVF_SQ8)
+            .withParamsInJson("{\"nlist\": 19384}")
+            .build();
+
+    Response createIndexResponse = client.createIndex(index);
     assertTrue(createIndexResponse.ok());
   }
 
   @org.junit.jupiter.api.Test
   void insert() {
-    List<List<Float>> vectors = generateVectors(size, dimension);
-    InsertParam insertParam = new InsertParam.Builder(randomTableName, vectors).build();
+    List<List<Float>> vectors = generateFloatVectors(size, dimension);
+    InsertParam insertParam =
+        new InsertParam.Builder(randomCollectionName).withFloatVectors(vectors).build();
+    InsertResponse insertResponse = client.insert(insertParam);
+    assertTrue(insertResponse.ok());
+    assertEquals(size, insertResponse.getVectorIds().size());
+  }
+
+  @org.junit.jupiter.api.Test
+  void insertBinary() {
+    final long binaryDimension = 10000;
+
+    String binaryCollectionName = generator.generate(10);
+    CollectionMapping collectionMapping =
+        new CollectionMapping.Builder(binaryCollectionName, binaryDimension)
+            .withIndexFileSize(1024)
+            .withMetricType(MetricType.JACCARD)
+            .build();
+
+    assertTrue(client.createCollection(collectionMapping).ok());
+
+    List<ByteBuffer> vectors = generateBinaryVectors(size, binaryDimension);
+    InsertParam insertParam =
+        new InsertParam.Builder(binaryCollectionName).withBinaryVectors(vectors).build();
     InsertResponse insertResponse = client.insert(insertParam);
     assertTrue(insertResponse.ok());
     assertEquals(size, insertResponse.getVectorIds().size());
+
+    assertTrue(client.dropCollection(binaryCollectionName).ok());
   }
 
   @org.junit.jupiter.api.Test
-  void search() throws InterruptedException {
-    List<List<Float>> vectors = generateVectors(size, dimension);
+  void search() {
+    List<List<Float>> vectors = generateFloatVectors(size, dimension);
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
-    InsertParam insertParam = new InsertParam.Builder(randomTableName, vectors).build();
+    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());
 
-    TimeUnit.SECONDS.sleep(1);
+    assertTrue(client.flush(randomCollectionName).ok());
 
     final int searchSize = 5;
     List<List<Float>> vectorsToSearch = vectors.subList(0, searchSize);
 
-    List<DateRange> queryRanges = new ArrayList<>();
-    Date today = new Date();
-    Calendar c = Calendar.getInstance();
-    c.setTime(today);
-    c.add(Calendar.DAY_OF_MONTH, -1);
-    Date yesterday = c.getTime();
-    c.setTime(today);
-    c.add(Calendar.DAY_OF_MONTH, 1);
-    Date tomorrow = c.getTime();
-    queryRanges.add(new DateRange(yesterday, tomorrow));
     final long topK = 10;
     SearchParam searchParam =
-        new SearchParam.Builder(randomTableName, vectorsToSearch)
+        new SearchParam.Builder(randomCollectionName)
+            .withFloatVectors(vectorsToSearch)
             .withTopK(topK)
-            .withNProbe(20)
-            .withDateRanges(queryRanges)
+            .withParamsInJson("{\"nprobe\": 20}")
             .build();
     SearchResponse searchResponse = client.search(searchParam);
     assertTrue(searchResponse.ok());
@@ -326,26 +361,82 @@ class MilvusClientTest {
     }
   }
 
+  @org.junit.jupiter.api.Test
+  void searchBinary() {
+    final long binaryDimension = 10000;
+
+    String binaryCollectionName = generator.generate(10);
+    CollectionMapping collectionMapping =
+        new CollectionMapping.Builder(binaryCollectionName, binaryDimension)
+            .withIndexFileSize(1024)
+            .withMetricType(MetricType.JACCARD)
+            .build();
+
+    assertTrue(client.createCollection(collectionMapping).ok());
+
+    List<ByteBuffer> vectors = generateBinaryVectors(size, binaryDimension);
+    InsertParam insertParam =
+        new InsertParam.Builder(binaryCollectionName).withBinaryVectors(vectors).build();
+    InsertResponse insertResponse = client.insert(insertParam);
+    assertTrue(insertResponse.ok());
+    List<Long> vectorIds = insertResponse.getVectorIds();
+    assertEquals(size, vectorIds.size());
+
+    assertTrue(client.flush(binaryCollectionName).ok());
+
+    final int searchSize = 5;
+    List<ByteBuffer> vectorsToSearch = vectors.subList(0, searchSize);
+
+    final long topK = 10;
+    SearchParam searchParam =
+        new SearchParam.Builder(binaryCollectionName)
+            .withBinaryVectors(vectorsToSearch)
+            .withTopK(topK)
+            .withParamsInJson("{\"nprobe\": 20}")
+            .build();
+    SearchResponse searchResponse = client.search(searchParam);
+    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(client.dropCollection(binaryCollectionName).ok());
+  }
+
   //    @org.junit.jupiter.api.Test
   //    void searchInFiles() {
   //    }
 
   @org.junit.jupiter.api.Test
-  void describeTable() {
-    DescribeTableResponse describeTableResponse = client.describeTable(randomTableName);
-    assertTrue(describeTableResponse.ok());
-    assertTrue(describeTableResponse.getTableSchema().isPresent());
-
-    String nonExistingTableName = generator.generate(10);
-    describeTableResponse = client.describeTable(nonExistingTableName);
-    assertFalse(describeTableResponse.ok());
-    assertFalse(describeTableResponse.getTableSchema().isPresent());
+  void describeCollection() {
+    DescribeCollectionResponse describeCollectionResponse =
+        client.describeCollection(randomCollectionName);
+    assertTrue(describeCollectionResponse.ok());
+    assertTrue(describeCollectionResponse.getCollectionMapping().isPresent());
+    assertEquals(
+        describeCollectionResponse.getCollectionMapping().get().getCollectionName(),
+        randomCollectionName);
+
+    String nonExistingCollectionName = generator.generate(10);
+    describeCollectionResponse = client.describeCollection(nonExistingCollectionName);
+    assertFalse(describeCollectionResponse.ok());
+    assertFalse(describeCollectionResponse.getCollectionMapping().isPresent());
   }
 
   @org.junit.jupiter.api.Test
-  void showTables() {
-    ShowTablesResponse showTablesResponse = client.showTables();
-    assertTrue(showTablesResponse.ok());
+  void showCollections() {
+    ShowCollectionsResponse showCollectionsResponse = client.showCollections();
+    assertTrue(showCollectionsResponse.ok());
+    assertEquals(showCollectionsResponse.getCollectionNames().get(0), randomCollectionName);
   }
 
   @org.junit.jupiter.api.Test
@@ -361,31 +452,194 @@ class MilvusClientTest {
   }
 
   @org.junit.jupiter.api.Test
-  void getTableRowCount() throws InterruptedException {
+  void getCollectionRowCount() {
     insert();
-    TimeUnit.SECONDS.sleep(1);
+    assertTrue(client.flush(randomCollectionName).ok());
 
-    GetTableRowCountResponse getTableRowCountResponse = client.getTableRowCount(randomTableName);
-    assertTrue(getTableRowCountResponse.ok());
-    assertEquals(size, getTableRowCountResponse.getTableRowCount());
+    GetCollectionRowCountResponse getCollectionRowCountResponse =
+        client.getCollectionRowCount(randomCollectionName);
+    assertTrue(getCollectionRowCountResponse.ok());
+    assertEquals(size, getCollectionRowCountResponse.getCollectionRowCount());
   }
 
   @org.junit.jupiter.api.Test
-  void preloadTable() {
-    Response preloadTableResponse = client.preloadTable(randomTableName);
-    assertTrue(preloadTableResponse.ok());
+  void preloadCollection() {
+    insert();
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    Response preloadCollectionResponse = client.preloadCollection(randomCollectionName);
+    assertTrue(preloadCollectionResponse.ok());
   }
 
   @org.junit.jupiter.api.Test
   void describeIndex() {
-    DescribeIndexResponse describeIndexResponse = client.describeIndex(randomTableName);
+    createIndex();
+
+    DescribeIndexResponse describeIndexResponse = client.describeIndex(randomCollectionName);
     assertTrue(describeIndexResponse.ok());
     assertTrue(describeIndexResponse.getIndex().isPresent());
+    assertEquals(describeIndexResponse.getIndex().get().getCollectionName(), randomCollectionName);
+    assertEquals(describeIndexResponse.getIndex().get().getIndexType(), IndexType.IVF_SQ8);
   }
 
   @org.junit.jupiter.api.Test
   void dropIndex() {
-    Response dropIndexResponse = client.dropIndex(randomTableName);
+    Response dropIndexResponse = client.dropIndex(randomCollectionName);
     assertTrue(dropIndexResponse.ok());
   }
+
+  @org.junit.jupiter.api.Test
+  void showCollectionInfo() {
+    insert();
+
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    ShowCollectionInfoResponse showCollectionInfoResponse =
+        client.showCollectionInfo(randomCollectionName);
+    assertTrue(showCollectionInfoResponse.ok());
+    assertTrue(showCollectionInfoResponse.getCollectionInfo().isPresent());
+
+    CollectionInfo collectionInfo = showCollectionInfoResponse.getCollectionInfo().get();
+    assertEquals(collectionInfo.getRowCount(), size);
+
+    CollectionInfo.PartitionInfo partitionInfo = collectionInfo.getPartitionInfos().get(0);
+    assertEquals(partitionInfo.getTag(), "_default");
+    assertEquals(partitionInfo.getRowCount(), size);
+
+    CollectionInfo.PartitionInfo.SegmentInfo segmentInfo = partitionInfo.getSegmentInfos().get(0);
+    assertEquals(segmentInfo.getRowCount(), size);
+    assertEquals(segmentInfo.getIndexName(), "IDMAP");
+  }
+
+  @org.junit.jupiter.api.Test
+  void getVectorById() {
+    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());
+
+    GetVectorByIdResponse getVectorByIdResponse =
+        client.getVectorById(randomCollectionName, vectorIds.get(0));
+    assertTrue(getVectorByIdResponse.ok());
+    assertTrue(getVectorByIdResponse.exists());
+    assertTrue(getVectorByIdResponse.isFloatVector());
+    assertFalse(getVectorByIdResponse.isBinaryVector());
+    assertArrayEquals(getVectorByIdResponse.getFloatVector().toArray(), vectors.get(0).toArray());
+  }
+
+  @org.junit.jupiter.api.Test
+  void getVectorIds() {
+    insert();
+
+    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);
+
+    GetVectorIdsResponse getVectorIdsResponse =
+        client.getVectorIds(randomCollectionName, segmentInfo.getSegmentName());
+    assertTrue(getVectorIdsResponse.ok());
+    assertFalse(getVectorIdsResponse.getIds().isEmpty());
+  }
+
+  @org.junit.jupiter.api.Test
+  void deleteByIds() {
+    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());
+
+    assertTrue(client.deleteByIds(randomCollectionName, vectorIds.subList(0, 100)).ok());
+    assertTrue(client.flush(randomCollectionName).ok());
+    assertEquals(
+        client.getCollectionRowCount(randomCollectionName).getCollectionRowCount(), size - 100);
+  }
+
+  @org.junit.jupiter.api.Test
+  void deleteById() {
+    List<List<Float>> vectors = generateFloatVectors(1, dimension);
+    InsertParam insertParam =
+        new InsertParam.Builder(randomCollectionName).withFloatVectors(vectors).build();
+    InsertResponse insertResponse = client.insert(insertParam);
+    assertTrue(insertResponse.ok());
+    List<Long> vectorIds = insertResponse.getVectorIds();
+    assertEquals(vectorIds.size(), 1);
+
+    assertTrue(client.flush(randomCollectionName).ok());
+
+    assertTrue(client.deleteById(randomCollectionName, vectorIds.get(0)).ok());
+    assertTrue(client.flush(randomCollectionName).ok());
+    assertEquals(client.getCollectionRowCount(randomCollectionName).getCollectionRowCount(), 0);
+  }
+
+  @org.junit.jupiter.api.Test
+  void flush() {
+    assertTrue(client.flush(randomCollectionName).ok());
+  }
+
+  @org.junit.jupiter.api.Test
+  void compact() {
+    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.compact(randomCollectionName).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);
+  }
 }