Browse Source

Merge pull request #65 from youny626/0.3.0

Release 0.3.0
Jin Hai 5 years ago
parent
commit
d7c44f54e6

+ 5 - 2
CHANGELOG.md

@@ -1,14 +1,17 @@
 # Changelog     
 # Changelog     
 
 
-## milvus-sdk-java 0.3.0 (TBD)
+## milvus-sdk-java 0.3.0 (2019-11-13)
 
 
 ### Bug
 ### Bug
 ---
 ---
+- \#64 - Search failed with exception if search result is empty
 
 
 ### Improvement
 ### Improvement
 ---
 ---
 - \#56 - Add keepalive and idleTimeout settings
 - \#56 - Add keepalive and idleTimeout settings
 - \#57 - add ok() in other types of Response
 - \#57 - add ok() in other types of Response
+- \#62 - Change GRPC proto (and related code) to increase search result's transmission speed
+- \#63 - Make some functions and constructors package-private if necessary
 
 
 ### Feature
 ### Feature
 ---
 ---
@@ -16,7 +19,7 @@
 ### Task
 ### Task
 ---
 ---
 
 
-## milvus-sdk-java 0.2.2 (2018-11-4)
+## milvus-sdk-java 0.2.2 (2019-11-4)
 
 
 ### Bug
 ### Bug
 ---
 ---

+ 4 - 2
README.md

@@ -15,6 +15,8 @@ Milvus version compatibility:
 |:-----:|:-----:|
 |:-----:|:-----:|
 | 0.5.0 | 0.2.2 | 
 | 0.5.0 | 0.2.2 | 
 | 0.5.1 | 0.2.2 | 
 | 0.5.1 | 0.2.2 | 
+| 0.5.2 | 0.2.2 | 
+| 0.5.3 | 0.3.0 | 
 
 
 ### Dependency 
 ### Dependency 
 
 
@@ -23,13 +25,13 @@ Apache Maven
 <dependency>
 <dependency>
     <groupId>io.milvus</groupId>
     <groupId>io.milvus</groupId>
     <artifactId>milvus-sdk-java</artifactId>
     <artifactId>milvus-sdk-java</artifactId>
-    <version>0.2.2</version>
+    <version>0.3.0</version>
 </dependency>
 </dependency>
 ```
 ```
 
 
 Gradle/Grails 
 Gradle/Grails 
 
 
-`compile 'io.milvus:milvus-sdk-java:0.2.2'`
+`compile 'io.milvus:milvus-sdk-java:0.3.0'`
 
 
 ### Examples
 ### Examples
 
 

+ 2 - 1
examples/pom.xml

@@ -45,6 +45,7 @@
     </properties>
     </properties>
 
 
     <!--  For development use  -->
     <!--  For development use  -->
+    <!--  Include this if you want to try the latest SNAPSHOT version  -->
     <repositories>
     <repositories>
         <repository>
         <repository>
             <id>oss.sonatype.org-snapshot</id>
             <id>oss.sonatype.org-snapshot</id>
@@ -62,7 +63,7 @@
         <dependency>
         <dependency>
             <groupId>io.milvus</groupId>
             <groupId>io.milvus</groupId>
             <artifactId>milvus-sdk-java</artifactId>
             <artifactId>milvus-sdk-java</artifactId>
-            <version>0.3.0-SNAPSHOT</version>
+            <version>0.3.0</version>
         </dependency>
         </dependency>
     </dependencies>
     </dependencies>
 
 

+ 6 - 1
pom.xml

@@ -25,7 +25,7 @@
 
 
     <groupId>io.milvus</groupId>
     <groupId>io.milvus</groupId>
     <artifactId>milvus-sdk-java</artifactId>
     <artifactId>milvus-sdk-java</artifactId>
-    <version>0.3.0-SNAPSHOT</version>
+    <version>0.3.0</version>
     <packaging>jar</packaging>
     <packaging>jar</packaging>
 
 
     <name>io.milvus:milvus-sdk-java</name>
     <name>io.milvus:milvus-sdk-java</name>
@@ -134,6 +134,11 @@
             <artifactId>commons-text</artifactId>
             <artifactId>commons-text</artifactId>
             <version>1.6</version>
             <version>1.6</version>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.4</version>
+        </dependency>
     </dependencies>
     </dependencies>
 
 
     <profiles>
     <profiles>

+ 2 - 2
src/main/java/io/milvus/client/ConnectParam.java

@@ -202,8 +202,8 @@ public class ConnectParam {
     }
     }
 
 
     /**
     /**
-     * Optional. Set the duration without ongoing RPCs before going to idle mode. Defaults to 24
-     * hour.
+     * Optional. Set the duration without ongoing RPCs before going to idle mode. A new RPC would
+     * take the channel out of idle mode. Defaults to 24 hour.
      *
      *
      * @see <a
      * @see <a
      *     href="https://grpc.github.io/grpc-java/javadoc/io/grpc/ManagedChannelBuilder.html#idleTimeout-long-java.util.concurrent.TimeUnit-">
      *     href="https://grpc.github.io/grpc-java/javadoc/io/grpc/ManagedChannelBuilder.html#idleTimeout-long-java.util.concurrent.TimeUnit-">

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

@@ -29,7 +29,7 @@ public class DescribeIndexResponse {
   private final Response response;
   private final Response response;
   private final Index index;
   private final Index index;
 
 
-  public DescribeIndexResponse(Response response, @Nullable Index index) {
+  DescribeIndexResponse(Response response, @Nullable Index index) {
     this.response = response;
     this.response = response;
     this.index = index;
     this.index = index;
   }
   }

+ 1 - 1
src/main/java/io/milvus/client/DescribeTableResponse.java

@@ -30,7 +30,7 @@ public class DescribeTableResponse {
   private final Response response;
   private final Response response;
   private final TableSchema tableSchema;
   private final TableSchema tableSchema;
 
 
-  public DescribeTableResponse(Response response, @Nullable TableSchema tableSchema) {
+  DescribeTableResponse(Response response, @Nullable TableSchema tableSchema) {
     this.response = response;
     this.response = response;
     this.tableSchema = tableSchema;
     this.tableSchema = tableSchema;
   }
   }

+ 1 - 1
src/main/java/io/milvus/client/GetTableRowCountResponse.java

@@ -27,7 +27,7 @@ public class GetTableRowCountResponse {
   private final Response response;
   private final Response response;
   private final long tableRowCount;
   private final long tableRowCount;
 
 
-  public GetTableRowCountResponse(Response response, long tableRowCount) {
+  GetTableRowCountResponse(Response response, long tableRowCount) {
     this.response = response;
     this.response = response;
     this.tableRowCount = tableRowCount;
     this.tableRowCount = tableRowCount;
   }
   }

+ 1 - 1
src/main/java/io/milvus/client/HasTableResponse.java

@@ -26,7 +26,7 @@ public class HasTableResponse {
   private final Response response;
   private final Response response;
   private final boolean hasTable;
   private final boolean hasTable;
 
 
-  public HasTableResponse(Response response, boolean hasTable) {
+  HasTableResponse(Response response, boolean hasTable) {
     this.response = response;
     this.response = response;
     this.hasTable = hasTable;
     this.hasTable = hasTable;
   }
   }

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

@@ -28,7 +28,7 @@ public class InsertResponse {
   private final Response response;
   private final Response response;
   private final List<Long> vectorIds;
   private final List<Long> vectorIds;
 
 
-  public InsertResponse(Response response, List<Long> vectorIds) {
+  InsertResponse(Response response, List<Long> vectorIds) {
     this.response = response;
     this.response = response;
     this.vectorIds = vectorIds;
     this.vectorIds = vectorIds;
   }
   }

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

@@ -56,7 +56,8 @@ public interface MilvusClient {
    */
    */
   Response connect(ConnectParam connectParam) throws ConnectFailedException;
   Response connect(ConnectParam connectParam) throws ConnectFailedException;
 
 
-  /** @return <code>true</code> if the client is connected to Milvus server */
+  /** @return <code>true</code> if the client is connected to Milvus server.
+   * The channel's connectivity state is READY.*/
   boolean isConnected();
   boolean isConnected();
 
 
   /**
   /**

+ 57 - 43
src/main/java/io/milvus/client/MilvusGrpcClient.java

@@ -23,6 +23,7 @@ import io.grpc.ConnectivityState;
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.StatusRuntimeException;
 import io.grpc.StatusRuntimeException;
+import org.apache.commons.collections4.ListUtils;
 
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nonnull;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
@@ -69,8 +70,7 @@ public class MilvusGrpcClient implements MilvusClient {
               .idleTimeout(connectParam.getIdleTimeout(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS)
               .idleTimeout(connectParam.getIdleTimeout(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS)
               .build();
               .build();
 
 
-      ConnectivityState connectivityState;
-      connectivityState = channel.getState(true);
+      channel.getState(true);
 
 
       long timeout = connectParam.getConnectTimeout(TimeUnit.MILLISECONDS);
       long timeout = connectParam.getConnectTimeout(TimeUnit.MILLISECONDS);
       logInfo("Trying to connect...Timeout in {0} ms", timeout);
       logInfo("Trying to connect...Timeout in {0} ms", timeout);
@@ -94,7 +94,9 @@ public class MilvusGrpcClient implements MilvusClient {
       throw new ConnectFailedException("Exception occurred: " + e.toString());
       throw new ConnectFailedException("Exception occurred: " + e.toString());
     }
     }
 
 
-    logInfo("Connected successfully!\n{0}", connectParam.toString());
+    logInfo(
+        "Connection established successfully to host={0}, port={1}",
+        connectParam.getHost(), connectParam.getPort());
     return new Response(Response.Status.SUCCESS);
     return new Response(Response.Status.SUCCESS);
   }
   }
 
 
@@ -321,8 +323,9 @@ public class MilvusGrpcClient implements MilvusClient {
 
 
     if (!channelIsReadyOrIdle()) {
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
       logWarning("You are not connected to Milvus server");
-      return new SearchResponse(
-          new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
+      SearchResponse searchResponse = new SearchResponse();
+      searchResponse.setResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED));
+      return searchResponse;
     }
     }
 
 
     List<io.milvus.grpc.RowRecord> queryRowRecordList = getQueryRowRecordList(searchParam);
     List<io.milvus.grpc.RowRecord> queryRowRecordList = getQueryRowRecordList(searchParam);
@@ -338,29 +341,32 @@ public class MilvusGrpcClient implements MilvusClient {
             .setNprobe(searchParam.getNProbe())
             .setNprobe(searchParam.getNProbe())
             .build();
             .build();
 
 
-    io.milvus.grpc.TopKQueryResultList response;
+    io.milvus.grpc.TopKQueryResult response;
 
 
     try {
     try {
       response = blockingStub.search(request);
       response = blockingStub.search(request);
 
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
-        List<List<SearchResponse.QueryResult>> queryResultsList = getQueryResultsList(response);
+        SearchResponse searchResponse = buildSearchResponse(response);
+        searchResponse.setResponse(new Response(Response.Status.SUCCESS));
         logInfo(
         logInfo(
             "Search completed successfully! Returned results for {0} queries",
             "Search completed successfully! Returned results for {0} queries",
-            queryResultsList.size());
-        return new SearchResponse(new Response(Response.Status.SUCCESS), queryResultsList);
+            searchResponse.getNumQueries());
+        return searchResponse;
       } else {
       } else {
         logSevere("Search failed:\n{0}", response.toString());
         logSevere("Search failed:\n{0}", response.toString());
-        return new SearchResponse(
+        SearchResponse searchResponse = new SearchResponse();
+        searchResponse.setResponse(
             new Response(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
-                response.getStatus().getReason()),
-            new ArrayList<>());
+                response.getStatus().getReason()));
+        return searchResponse;
       }
       }
     } catch (StatusRuntimeException e) {
     } catch (StatusRuntimeException e) {
       logSevere("search RPC failed:\n{0}", e.getStatus().toString());
       logSevere("search RPC failed:\n{0}", e.getStatus().toString());
-      return new SearchResponse(
-          new Response(Response.Status.RPC_ERROR, e.toString()), new ArrayList<>());
+      SearchResponse searchResponse = new SearchResponse();
+      searchResponse.setResponse(new Response(Response.Status.RPC_ERROR, e.toString()));
+      return searchResponse;
     }
     }
   }
   }
 
 
@@ -369,8 +375,9 @@ public class MilvusGrpcClient implements MilvusClient {
 
 
     if (!channelIsReadyOrIdle()) {
     if (!channelIsReadyOrIdle()) {
       logWarning("You are not connected to Milvus server");
       logWarning("You are not connected to Milvus server");
-      return new SearchResponse(
-          new Response(Response.Status.CLIENT_NOT_CONNECTED), new ArrayList<>());
+      SearchResponse searchResponse = new SearchResponse();
+      searchResponse.setResponse(new Response(Response.Status.CLIENT_NOT_CONNECTED));
+      return searchResponse;
     }
     }
 
 
     SearchParam searchParam = searchInFilesParam.getSearchParam();
     SearchParam searchParam = searchInFilesParam.getSearchParam();
@@ -394,30 +401,33 @@ public class MilvusGrpcClient implements MilvusClient {
             .setSearchParam(searchParamToSet)
             .setSearchParam(searchParamToSet)
             .build();
             .build();
 
 
-    io.milvus.grpc.TopKQueryResultList response;
+    io.milvus.grpc.TopKQueryResult response;
 
 
     try {
     try {
       response = blockingStub.searchInFiles(request);
       response = blockingStub.searchInFiles(request);
 
 
       if (response.getStatus().getErrorCode() == io.milvus.grpc.ErrorCode.SUCCESS) {
       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 {0} completed successfully!", searchInFilesParam.getFileIds());
-
-        List<List<SearchResponse.QueryResult>> queryResultsList = getQueryResultsList(response);
-        return new SearchResponse(new Response(Response.Status.SUCCESS), queryResultsList);
+        return searchResponse;
       } else {
       } else {
         logSevere(
         logSevere(
             "Search in files {0} failed:\n{1}",
             "Search in files {0} failed:\n{1}",
             searchInFilesParam.getFileIds(), response.toString());
             searchInFilesParam.getFileIds(), response.toString());
-        return new SearchResponse(
+
+        SearchResponse searchResponse = new SearchResponse();
+        searchResponse.setResponse(
             new Response(
             new Response(
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
                 Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
-                response.getStatus().getReason()),
-            new ArrayList<>());
+                response.getStatus().getReason()));
+        return searchResponse;
       }
       }
     } catch (StatusRuntimeException e) {
     } catch (StatusRuntimeException e) {
       logSevere("searchInFiles RPC failed:\n{0}", e.getStatus().toString());
       logSevere("searchInFiles RPC failed:\n{0}", e.getStatus().toString());
-      return new SearchResponse(
-          new Response(Response.Status.RPC_ERROR, e.toString()), new ArrayList<>());
+      SearchResponse searchResponse = new SearchResponse();
+      searchResponse.setResponse(new Response(Response.Status.RPC_ERROR, e.toString()));
+      return searchResponse;
     }
     }
   }
   }
 
 
@@ -728,25 +738,29 @@ public class MilvusGrpcClient implements MilvusClient {
         .build();
         .build();
   }
   }
 
 
-  private List<List<SearchResponse.QueryResult>> getQueryResultsList(
-      io.milvus.grpc.TopKQueryResultList searchResponse) {
-    // TODO: refactor
-    List<List<SearchResponse.QueryResult>> queryResultsList = new ArrayList<>();
-    Optional<List<io.milvus.grpc.TopKQueryResult>> topKQueryResultList =
-        Optional.ofNullable(searchResponse.getTopkQueryResultList());
-    if (topKQueryResultList.isPresent()) {
-      for (io.milvus.grpc.TopKQueryResult topKQueryResult : topKQueryResultList.get()) {
-        List<SearchResponse.QueryResult> responseQueryResults = new ArrayList<>();
-        List<io.milvus.grpc.QueryResult> queryResults = topKQueryResult.getQueryResultArraysList();
-        for (io.milvus.grpc.QueryResult queryResult : queryResults) {
-          SearchResponse.QueryResult responseQueryResult =
-              new SearchResponse.QueryResult(queryResult.getId(), queryResult.getDistance());
-          responseQueryResults.add(responseQueryResult);
-        }
-        queryResultsList.add(responseQueryResults);
-      }
+  private SearchResponse buildSearchResponse(io.milvus.grpc.TopKQueryResult topKQueryResult) {
+
+    final int numQueries = (int) topKQueryResult.getRowNum();
+    final int topK =
+        numQueries == 0
+            ? 0
+            : topKQueryResult.getIdsCount()
+                / numQueries; // Guaranteed to be divisible from server side
+
+    List<List<Long>> resultIdsList = new ArrayList<>();
+    List<List<Float>> resultDistancesList = new ArrayList<>();
+    if (topK > 0) {
+      resultIdsList = ListUtils.partition(topKQueryResult.getIdsList(), topK);
+      resultDistancesList = ListUtils.partition(topKQueryResult.getDistancesList(), topK);
     }
     }
-    return queryResultsList;
+
+    SearchResponse searchResponse = new SearchResponse();
+    searchResponse.setNumQueries(numQueries);
+    searchResponse.setTopK(topK);
+    searchResponse.setResultIdsList(resultIdsList);
+    searchResponse.setResultDistancesList(resultDistancesList);
+
+    return searchResponse;
   }
   }
 
 
   private boolean channelIsReadyOrIdle() {
   private boolean channelIsReadyOrIdle() {

+ 50 - 29
src/main/java/io/milvus/client/SearchResponse.java

@@ -19,8 +19,10 @@
 
 
 package io.milvus.client;
 package io.milvus.client;
 
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
 
 
 /**
 /**
  * Contains the returned <code>response</code> and <code>queryResultsList</code> for <code>search
  * Contains the returned <code>response</code> and <code>queryResultsList</code> for <code>search
@@ -28,12 +30,26 @@ import java.util.List;
  */
  */
 public class SearchResponse {
 public class SearchResponse {
 
 
-  private final Response response;
-  private final List<List<QueryResult>> queryResultsList;
+  private Response response;
+  private int numQueries;
+  private long topK;
+  private List<List<Long>> resultIdsList;
+  private List<List<Float>> resultDistancesList;
 
 
-  public SearchResponse(Response response, List<List<QueryResult>> queryResultsList) {
-    this.response = response;
-    this.queryResultsList = queryResultsList;
+  public int getNumQueries() {
+    return numQueries;
+  }
+
+  void setNumQueries(int numQueries) {
+    this.numQueries = numQueries;
+  }
+
+  public long getTopK() {
+    return topK;
+  }
+
+  void setTopK(long topK) {
+    this.topK = topK;
   }
   }
 
 
   /**
   /**
@@ -41,7 +57,17 @@ public class SearchResponse {
    *     the query result of a vector.
    *     the query result of a vector.
    */
    */
   public List<List<QueryResult>> getQueryResultsList() {
   public List<List<QueryResult>> getQueryResultsList() {
-    return queryResultsList;
+    return IntStream.range(0, numQueries)
+        .mapToObj(
+            i ->
+                LongStream.range(0, topK)
+                    .mapToObj(
+                        j ->
+                            new QueryResult(
+                                resultIdsList.get(i).get((int) j),
+                                resultDistancesList.get(i).get((int) j)))
+                    .collect(Collectors.toList()))
+        .collect(Collectors.toList());
   }
   }
 
 
   /**
   /**
@@ -49,37 +75,33 @@ public class SearchResponse {
    *     of a vector.
    *     of a vector.
    */
    */
   public List<List<Long>> getResultIdsList() {
   public List<List<Long>> getResultIdsList() {
-    List<List<Long>> resultIdsList = new ArrayList<>();
-    for (List<QueryResult> queryResults : queryResultsList) {
-      List<Long> resultIds = new ArrayList<>();
-      for (QueryResult queryResult : queryResults) {
-        resultIds.add(queryResult.vectorId);
-      }
-      resultIdsList.add(resultIds);
-    }
     return resultIdsList;
     return resultIdsList;
   }
   }
 
 
+  void setResultIdsList(List<List<Long>> resultIdsList) {
+    this.resultIdsList = resultIdsList;
+  }
+
   /**
   /**
    * @return @return a <code>List</code> of result distances. Each inner <code>List</code> contains
    * @return @return a <code>List</code> of result distances. Each inner <code>List</code> contains
    *     the result distances of a vector.
    *     the result distances of a vector.
    */
    */
-  public List<List<Double>> getResultDistancesList() {
-    List<List<Double>> resultDistancesList = new ArrayList<>();
-    for (List<QueryResult> queryResults : queryResultsList) {
-      List<Double> resultDistances = new ArrayList<>();
-      for (QueryResult queryResult : queryResults) {
-        resultDistances.add(queryResult.distance);
-      }
-      resultDistancesList.add(resultDistances);
-    }
+  public List<List<Float>> getResultDistancesList() {
     return resultDistancesList;
     return resultDistancesList;
   }
   }
 
 
+  void setResultDistancesList(List<List<Float>> resultDistancesList) {
+    this.resultDistancesList = resultDistancesList;
+  }
+
   public Response getResponse() {
   public Response getResponse() {
     return response;
     return response;
   }
   }
 
 
+  void setResponse(Response response) {
+    this.response = response;
+  }
+
   public boolean ok() {
   public boolean ok() {
     return response.ok();
     return response.ok();
   }
   }
@@ -87,8 +109,7 @@ public class SearchResponse {
   @Override
   @Override
   public String toString() {
   public String toString() {
     return String.format(
     return String.format(
-        "SearchResponse {%s, returned results for %d queries}",
-        response.toString(), this.queryResultsList.size());
+        "SearchResponse {%s, returned results for %d queries}", response.toString(), numQueries);
   }
   }
 
 
   /**
   /**
@@ -97,9 +118,9 @@ public class SearchResponse {
    */
    */
   public static class QueryResult {
   public static class QueryResult {
     private final long vectorId;
     private final long vectorId;
-    private final double distance;
+    private final float distance;
 
 
-    public QueryResult(long vectorId, double distance) {
+    QueryResult(long vectorId, float distance) {
       this.vectorId = vectorId;
       this.vectorId = vectorId;
       this.distance = distance;
       this.distance = distance;
     }
     }
@@ -108,7 +129,7 @@ public class SearchResponse {
       return vectorId;
       return vectorId;
     }
     }
 
 
-    public double getDistance() {
+    public float getDistance() {
       return distance;
       return distance;
     }
     }
   }
   }

+ 1 - 1
src/main/java/io/milvus/client/ShowTablesResponse.java

@@ -29,7 +29,7 @@ public class ShowTablesResponse {
   private final Response response;
   private final Response response;
   private final List<String> tableNames;
   private final List<String> tableNames;
 
 
-  public ShowTablesResponse(Response response, List<String> tableNames) {
+  ShowTablesResponse(Response response, List<String> tableNames) {
     this.response = response;
     this.response = response;
     this.tableNames = tableNames;
     this.tableNames = tableNames;
   }
   }

+ 272 - 31
src/main/proto/milvus.proto

@@ -9,319 +9,560 @@ option java_outer_classname = "MilvusProto";
 package milvus.grpc;
 package milvus.grpc;
 
 
 /**
 /**
+
  * @brief Table Name
  * @brief Table Name
+
  */
  */
+
 message TableName {
 message TableName {
+
     string table_name = 1;
     string table_name = 1;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Table Name List
  * @brief Table Name List
+
  */
  */
+
 message TableNameList {
 message TableNameList {
+
     Status status = 1;
     Status status = 1;
+
     repeated string table_names = 2;
     repeated string table_names = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Table Schema
  * @brief Table Schema
+
  */
  */
+
 message TableSchema {
 message TableSchema {
+
     Status status = 1;
     Status status = 1;
+
     string table_name = 2;
     string table_name = 2;
+
     int64 dimension = 3;
     int64 dimension = 3;
+
     int64 index_file_size = 4;
     int64 index_file_size = 4;
+
     int32 metric_type = 5;
     int32 metric_type = 5;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Range Schema
  * @brief Range Schema
+
  */
  */
+
 message Range {
 message Range {
+
     string start_value = 1;
     string start_value = 1;
+
     string end_value = 2;
     string end_value = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Record inserted
  * @brief Record inserted
+
  */
  */
+
 message RowRecord {
 message RowRecord {
-    repeated float vector_data = 1;             //binary vector data
+
+    repeated float vector_data = 1; //binary vector data
+
 }
 }
 
 
 /**
 /**
+
  * @brief params to be inserted
  * @brief params to be inserted
+
  */
  */
+
 message InsertParam {
 message InsertParam {
+
     string table_name = 1;
     string table_name = 1;
+
     repeated RowRecord row_record_array = 2;
     repeated RowRecord row_record_array = 2;
-    repeated int64 row_id_array = 3;            //optional
+
+    repeated int64 row_id_array = 3; //optional
+
 }
 }
 
 
 /**
 /**
+
  * @brief Vector ids
  * @brief Vector ids
+
  */
  */
+
 message VectorIds {
 message VectorIds {
+
     Status status = 1;
     Status status = 1;
+
     repeated int64 vector_id_array = 2;
     repeated int64 vector_id_array = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief params for searching vector
  * @brief params for searching vector
+
  */
  */
+
 message SearchParam {
 message SearchParam {
+
     string table_name = 1;
     string table_name = 1;
+
     repeated RowRecord query_record_array = 2;
     repeated RowRecord query_record_array = 2;
+
     repeated Range query_range_array = 3;
     repeated Range query_range_array = 3;
+
     int64 topk = 4;
     int64 topk = 4;
+
     int64 nprobe = 5;
     int64 nprobe = 5;
+
 }
 }
 
 
 /**
 /**
+
  * @brief params for searching vector in files
  * @brief params for searching vector in files
+
  */
  */
+
 message SearchInFilesParam {
 message SearchInFilesParam {
+
     repeated string file_id_array = 1;
     repeated string file_id_array = 1;
+
     SearchParam search_param = 2;
     SearchParam search_param = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Query result params
  * @brief Query result params
- */
-message QueryResult {
-    int64 id = 1;
-    double distance = 2;
-}
 
 
-/**
- * @brief TopK query result
  */
  */
+
 message TopKQueryResult {
 message TopKQueryResult {
-    repeated QueryResult query_result_arrays = 1;
-}
 
 
-/**
- * @brief List of topK query result
- */
-message TopKQueryResultList {
     Status status = 1;
     Status status = 1;
-    repeated TopKQueryResult topk_query_result = 2;
+
+    int64 row_num = 2;
+
+    repeated int64 ids = 3;
+
+    repeated float distances = 4;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Server String Reply
  * @brief Server String Reply
+
  */
  */
+
 message StringReply {
 message StringReply {
+
     Status status = 1;
     Status status = 1;
+
     string string_reply = 2;
     string string_reply = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Server bool Reply
  * @brief Server bool Reply
+
  */
  */
+
 message BoolReply {
 message BoolReply {
+
     Status status = 1;
     Status status = 1;
+
     bool bool_reply = 2;
     bool bool_reply = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Return table row count
  * @brief Return table row count
+
  */
  */
+
 message TableRowCount {
 message TableRowCount {
+
     Status status = 1;
     Status status = 1;
+
     int64 table_row_count = 2;
     int64 table_row_count = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Give Server Command
  * @brief Give Server Command
+
  */
  */
+
 message Command {
 message Command {
+
     string cmd = 1;
     string cmd = 1;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Index
  * @brief Index
+
  * @index_type: 0-invalid, 1-idmap, 2-ivflat, 3-ivfsq8, 4-nsgmix
  * @index_type: 0-invalid, 1-idmap, 2-ivflat, 3-ivfsq8, 4-nsgmix
+
  * @metric_type: 1-L2, 2-IP
  * @metric_type: 1-L2, 2-IP
+
  */
  */
+
 message Index {
 message Index {
+
     int32 index_type = 1;
     int32 index_type = 1;
+
     int32 nlist = 2;
     int32 nlist = 2;
+
 }
 }
 
 
 /**
 /**
+
  * @brief Index params
  * @brief Index params
+
  */
  */
+
 message IndexParam {
 message IndexParam {
+
     Status status = 1;
     Status status = 1;
+
     string table_name = 2;
     string table_name = 2;
+
     Index index = 3;
     Index index = 3;
+
 }
 }
 
 
 /**
 /**
+
  * @brief table name and range for DeleteByRange
  * @brief table name and range for DeleteByRange
+
  */
  */
+
 message DeleteByRangeParam {
 message DeleteByRangeParam {
+
     Range range = 1;
     Range range = 1;
+
     string table_name = 2;
     string table_name = 2;
+
 }
 }
 
 
 service MilvusService {
 service MilvusService {
+
     /**
     /**
+
      * @brief Create table method
      * @brief Create table method
+
      *
      *
+
      * 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 param, use to provide table information to be created.
+
      *
      *
+
      */
      */
-    rpc CreateTable(TableSchema) returns (Status){}
+
+    rpc CreateTable (TableSchema) returns (Status) {
+    }
 
 
     /**
     /**
+
      * @brief Test table existence method
      * @brief Test table existence method
+
      *
      *
+
      * This method is used to test table existence.
      * This method is used to test table existence.
+
      *
      *
+
      * @param table_name, table name is going to be tested.
      * @param table_name, table name is going to be tested.
+
      *
      *
+
      */
      */
-    rpc HasTable(TableName) returns (BoolReply) {}
+
+    rpc HasTable (TableName) returns (BoolReply) {
+    }
 
 
     /**
     /**
+
      * @brief Delete table method
      * @brief Delete table method
+
      *
      *
+
      * This method is used to delete table.
      * This method is used to delete table.
+
      *
      *
+
      * @param table_name, table name is going to be deleted.
      * @param table_name, table name is going to be deleted.
+
      *
      *
+
      */
      */
-    rpc DropTable(TableName) returns (Status) {}
+
+    rpc DropTable (TableName) returns (Status) {
+    }
 
 
     /**
     /**
+
      * @brief Build index by table method
      * @brief Build index by table method
+
      *
      *
+
      * This method is used to build index by table in sync mode.
      * This method is used to build index by table in sync mode.
+
      *
      *
+
      * @param table_name, table is going to be built index.
      * @param table_name, table is going to be built index.
+
      *
      *
+
      */
      */
-    rpc CreateIndex(IndexParam) returns (Status) {}
+
+    rpc CreateIndex (IndexParam) returns (Status) {
+    }
 
 
     /**
     /**
+
      * @brief Add vector array to table
      * @brief Add vector array to table
+
      *
      *
+
      * This method is used to add vector array to table.
      * This method is used to add vector array to table.
+
      *
      *
+
      * @param table_name, table_name is inserted.
      * @param table_name, table_name is inserted.
+
      * @param record_array, vector array is inserted.
      * @param record_array, vector array is inserted.
+
      *
      *
+
      * @return vector id array
      * @return vector id array
+
      */
      */
-    rpc Insert(InsertParam) returns (VectorIds) {}
+
+    rpc Insert (InsertParam) returns (VectorIds) {
+    }
 
 
     /**
     /**
+
      * @brief Query vector
      * @brief Query vector
+
      *
      *
+
      * This method is used to query vector in table.
      * This method is used to query vector in table.
+
      *
      *
+
      * @param table_name, table_name is queried.
      * @param table_name, table_name is queried.
+
      * @param query_record_array, all vector are going to be 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 query_range_array, optional ranges for conditional search. If not specified, search whole table
+
      * @param topk, how many similarity vectors will be searched.
      * @param topk, how many similarity vectors will be searched.
+
      *
      *
+
      * @return query result array.
      * @return query result array.
+
      */
      */
-    rpc Search(SearchParam) returns (TopKQueryResultList) {}
+
+    rpc Search (SearchParam) returns (TopKQueryResult) {
+    }
 
 
     /**
     /**
+
      * @brief Internal use query interface
      * @brief Internal use query interface
+
      *
      *
+
      * This method is used to query vector in specified files.
      * This method is used to query vector in specified files.
+
      *
      *
+
      * @param file_id_array, specified files id array, queried.
      * @param file_id_array, specified files id array, queried.
+
      * @param query_record_array, all vector are going to be 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 query_range_array, optional ranges for conditional search. If not specified, search whole table
+
      * @param topk, how many similarity vectors will be searched.
      * @param topk, how many similarity vectors will be searched.
+
      *
      *
+
      * @return query result array.
      * @return query result array.
+
      */
      */
-    rpc SearchInFiles(SearchInFilesParam) returns (TopKQueryResultList) {}
+
+    rpc SearchInFiles (SearchInFilesParam) returns (TopKQueryResult) {
+    }
 
 
     /**
     /**
+
      * @brief Get table schema
      * @brief Get table schema
+
      *
      *
+
      * This method is used to get table schema.
      * This method is used to get table schema.
+
      *
      *
+
      * @param table_name, target table name.
      * @param table_name, target table name.
+
      *
      *
+
      * @return table schema
      * @return table schema
+
      */
      */
-    rpc DescribeTable(TableName) returns (TableSchema) {}
+
+    rpc DescribeTable (TableName) returns (TableSchema) {
+    }
 
 
     /**
     /**
+
      * @brief Get table schema
      * @brief Get table schema
+
      *
      *
+
      * This method is used to get table schema.
      * This method is used to get table schema.
+
      *
      *
+
      * @param table_name, target table name.
      * @param table_name, target table name.
+
      *
      *
+
      * @return table schema
      * @return table schema
+
      */
      */
-    rpc CountTable(TableName) returns (TableRowCount) {}
+
+    rpc CountTable (TableName) returns (TableRowCount) {
+    }
 
 
     /**
     /**
+
      * @brief List all tables in database
      * @brief List all tables in database
+
      *
      *
+
      * This method is used to list all tables.
      * This method is used to list all tables.
+
      *
      *
+
      *
      *
+
      * @return table names.
      * @return table names.
+
      */
      */
-    rpc ShowTables(Command) returns (TableNameList) {}
+
+    rpc ShowTables (Command) returns (TableNameList) {
+    }
 
 
     /**
     /**
+
      * @brief Give the server status
      * @brief Give the server status
+
      *
      *
+
      * This method is used to give the server status.
      * This method is used to give the server status.
+
      *
      *
+
      * @return Server status.
      * @return Server status.
+
      */
      */
-    rpc Cmd(Command) returns (StringReply) {}
+
+    rpc Cmd (Command) returns (StringReply) {
+    }
 
 
     /**
     /**
+
     * @brief delete table by range
     * @brief delete table by range
+
     *
     *
+
     * This method is used to delete vector by range
     * This method is used to delete vector by range
+
     *
     *
+
     * @return rpc status.
     * @return rpc status.
+
     */
     */
-    rpc DeleteByRange(DeleteByRangeParam) returns (Status) {}
+
+    rpc DeleteByRange (DeleteByRangeParam) returns (Status) {
+    }
 
 
     /**
     /**
+
      * @brief preload table
      * @brief preload table
+
      *
      *
+
      * This method is used to preload table
      * This method is used to preload table
+
      *
      *
+
      * @return Status.
      * @return Status.
+
      */
      */
-    rpc PreloadTable(TableName) returns (Status) {}
+
+    rpc PreloadTable (TableName) returns (Status) {
+    }
 
 
     /**
     /**
+
      * @brief describe index
      * @brief describe index
+
      *
      *
+
      * This method is used to describe index
      * This method is used to describe index
+
      *
      *
+
      * @return Status.
      * @return Status.
+
      */
      */
-    rpc DescribeIndex(TableName) returns (IndexParam) {}
+
+    rpc DescribeIndex (TableName) returns (IndexParam) {
+    }
 
 
     /**
     /**
+
      * @brief drop index
      * @brief drop index
+
      *
      *
+
      * This method is used to drop index
      * This method is used to drop index
+
      *
      *
+
      * @return Status.
      * @return Status.
+
      */
      */
-    rpc DropIndex(TableName) returns (Status) {}
+
+    rpc DropIndex (TableName) returns (Status) {
+    }
 
 
 }
 }

+ 7 - 2
src/test/java/io/milvus/client/MilvusGrpcClientTest.java

@@ -215,7 +215,7 @@ class MilvusClientTest {
     c.add(Calendar.DAY_OF_MONTH, 1);
     c.add(Calendar.DAY_OF_MONTH, 1);
     Date tomorrow = c.getTime();
     Date tomorrow = c.getTime();
     queryRanges.add(new DateRange(yesterday, tomorrow));
     queryRanges.add(new DateRange(yesterday, tomorrow));
-    final long topK = 1000;
+    final long topK = 10;
     SearchParam searchParam =
     SearchParam searchParam =
         new SearchParam.Builder(randomTableName, vectorsToSearch)
         new SearchParam.Builder(randomTableName, vectorsToSearch)
             .withTopK(topK)
             .withTopK(topK)
@@ -224,14 +224,19 @@ class MilvusClientTest {
             .build();
             .build();
     SearchResponse searchResponse = client.search(searchParam);
     SearchResponse searchResponse = client.search(searchParam);
     assertTrue(searchResponse.ok());
     assertTrue(searchResponse.ok());
-    System.out.println(searchResponse);
+    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();
     List<List<SearchResponse.QueryResult>> queryResultsList = searchResponse.getQueryResultsList();
     assertEquals(searchSize, queryResultsList.size());
     assertEquals(searchSize, queryResultsList.size());
     final double epsilon = 0.001;
     final double epsilon = 0.001;
     for (int i = 0; i < searchSize; i++) {
     for (int i = 0; i < searchSize; i++) {
       SearchResponse.QueryResult firstQueryResult = queryResultsList.get(i).get(0);
       SearchResponse.QueryResult firstQueryResult = queryResultsList.get(i).get(0);
       assertEquals(vectorIds.get(i), firstQueryResult.getVectorId());
       assertEquals(vectorIds.get(i), firstQueryResult.getVectorId());
+      assertEquals(vectorIds.get(i), resultIdsList.get(i).get(0));
       assertTrue(Math.abs(1 - firstQueryResult.getDistance()) < epsilon);
       assertTrue(Math.abs(1 - firstQueryResult.getDistance()) < epsilon);
+      assertTrue(Math.abs(1 - resultDistancesList.get(i).get(0)) < epsilon);
     }
     }
   }
   }