Browse Source

first workable implementation :D

zhiru 5 years ago
parent
commit
3145036241

+ 0 - 5
pom.xml

@@ -71,11 +71,6 @@
             <version>2.25.1</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.javatuples</groupId>
-            <artifactId>javatuples</artifactId>
-            <version>1.2</version>
-        </dependency>
     </dependencies>
 
     <build>

+ 437 - 52
src/main/java/io/milvus/client/MilvusGrpcClient.java

@@ -4,16 +4,12 @@ import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.StatusRuntimeException;
 
-import io.milvus.client.grpc.RowRecord;
-import io.milvus.client.grpc.VectorIds;
 import io.milvus.client.params.*;
-import org.javatuples.Pair;
+import io.milvus.client.response.*;
 
 import javax.annotation.Nonnull;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.Random;
+import java.text.SimpleDateFormat;
+import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -61,19 +57,22 @@ public class MilvusGrpcClient {
             response = blockingStub.createTable(request);
 
             if (response.getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
-                logInfo("Created table successfully!\nTableSchema = {0}", tableSchema.toString());
+                logInfo("Created table successfully!\n{0}", tableSchema.toString());
                 return new Response(Response.Status.SUCCESS);
+            } else if (response.getReason().contentEquals("Table already exists")) {
+                logWarning("Table `{0}` already exists", tableSchema.getTableName());
+                return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
             } else {
-                logSevere("Create table failed\nTableSchema = {0}", tableSchema.toString());
+                logSevere("Create table failed\n{0}", tableSchema.toString());
                 return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
             }
         } catch (StatusRuntimeException e) {
-            logSevere("Create table RPC failed: {0}", e.getStatus().toString());
+            logSevere("createTable RPC failed:\n{0}", e.getStatus().toString());
             return new Response(Response.Status.RPC_ERROR, e.toString());
         }
     }
 
-    public boolean hasTable(@Nonnull String tableName) {
+    public HasTableResponse hasTable(@Nonnull String tableName) {
         io.milvus.client.grpc.TableName request = io.milvus.client.grpc.TableName
                                                  .newBuilder()
                                                  .setTableName(tableName)
@@ -84,15 +83,17 @@ public class MilvusGrpcClient {
             response = blockingStub.hasTable(request);
 
             if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
-                logInfo("hasTable \'{0}\' = {1}", tableName, response.getBoolReply());
-                return response.getBoolReply();
+                logInfo("hasTable `{0}` = {1}", tableName, response.getBoolReply());
+                return new HasTableResponse(Response.Status.SUCCESS, response.getBoolReply());
             } else {
-                logSevere("hasTable failed: ", response.toString());
-                return false;
+                logSevere("hasTable `{0}` failed:\n{1}", tableName, response.toString());
+                return new HasTableResponse(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                                            response.getStatus().getReason(),
+                                            false);
             }
         } catch (StatusRuntimeException e) {
-            logSevere("hasTable RPC failed: {0}", e.getStatus().toString());
-            return false;
+            logSevere("hasTable RPC failed:\n{0}", e.getStatus().toString());
+            return new HasTableResponse(Response.Status.RPC_ERROR, e.toString(), false);
         }
     }
 
@@ -107,14 +108,14 @@ public class MilvusGrpcClient {
             response = blockingStub.dropTable(request);
 
             if (response.getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
-                logInfo("Dropped table \'{0}\' successfully!", tableName);
+                logInfo("Dropped table `{0}` successfully!", tableName);
                 return new Response(Response.Status.SUCCESS);
             } else {
-                logSevere("Drop table \'{0}\' failed", tableName);
+                logSevere("Drop table `{0}` failed", tableName);
                 return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
             }
         } catch (StatusRuntimeException e) {
-            logSevere("Drop table RPC failed: {0}", e.getStatus().toString());
+            logSevere("dropTable RPC failed:\n{0}", e.getStatus().toString());
             return new Response(Response.Status.RPC_ERROR, e.toString());
         }
     }
@@ -123,7 +124,7 @@ public class MilvusGrpcClient {
         io.milvus.client.grpc.Index index = io.milvus.client.grpc.Index
                                             .newBuilder()
                                             .setIndexType(indexParam.getIndex().getIndexType().getVal())
-                                            .setNlist(indexParam.getIndex().getnNList())
+                                            .setNlist(indexParam.getIndex().getNList())
                                             .build();
         io.milvus.client.grpc.IndexParam request = io.milvus.client.grpc.IndexParam
                                            .newBuilder()
@@ -137,19 +138,19 @@ public class MilvusGrpcClient {
             response = blockingStub.createIndex(request);
 
             if (response.getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
-                logInfo("Created index successfully!\nIndexParam = {0}", indexParam.toString());
+                logInfo("Created index successfully!\n{0}", indexParam.toString());
                 return new Response(Response.Status.SUCCESS);
             } else {
-                logSevere("Create index failed\nIndexParam = {0}", indexParam.toString());
+                logSevere("Create index failed\n{0}", indexParam.toString());
                 return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
             }
         } catch (StatusRuntimeException e) {
-            logSevere("Create index RPC failed: {0}", e.getStatus().toString());
+            logSevere("createIndex RPC failed:\n{0}", e.getStatus().toString());
             return new Response(Response.Status.RPC_ERROR, e.toString());
         }
     }
 
-    public Pair<Response, Optional<List<Long>>> insert(@Nonnull InsertParam insertParam) {
+    public InsertResponse insert(@Nonnull InsertParam insertParam) {
 
         List<io.milvus.client.grpc.RowRecord> rowRecordList = new ArrayList<>();
         for (List<Float> vectors : insertParam.getVectors()) {
@@ -170,45 +171,381 @@ public class MilvusGrpcClient {
 
         try {
             response = blockingStub.insert(request);
-            Optional<List<Long>> resultVectorIds = Optional.ofNullable(response.getVectorIdArrayList());
 
             if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
                 logInfo("Inserted vectors successfully!");
-                return Pair.with(new Response(Response.Status.SUCCESS), resultVectorIds);
+                Optional<List<Long>> resultVectorIds = Optional.ofNullable(response.getVectorIdArrayList());
+                return new InsertResponse(Response.Status.SUCCESS, resultVectorIds.orElse(new ArrayList<>()));
             } else {
                 logSevere("Insert vectors failed");
-                return Pair.with(new Response(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
-                                              response.getStatus().getReason()),
-                                 Optional.empty());
+                return new InsertResponse(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                                          response.getStatus().getReason(),
+                                          new ArrayList<>());
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("insert RPC failed:\n{0}", e.getStatus().toString());
+            return new InsertResponse(Response.Status.RPC_ERROR, e.toString(), new ArrayList<>());
+        }
+    }
+
+    public SearchResponse search(@Nonnull SearchParam searchParam) {
+
+        List<io.milvus.client.grpc.RowRecord> queryRowRecordList = getQueryRowRecordList(searchParam);
+
+        List<io.milvus.client.grpc.Range> queryRangeList = getQueryRangeList(searchParam);
+
+        io.milvus.client.grpc.SearchParam request = io.milvus.client.grpc.SearchParam
+                                                    .newBuilder()
+                                                    .setTableName(searchParam.getTableName())
+                                                    .addAllQueryRecordArray(queryRowRecordList)
+                                                    .addAllQueryRangeArray(queryRangeList)
+                                                    .setTopk(searchParam.getTopK())
+                                                    .setNprobe(searchParam.getNProbe())
+                                                    .build();
+
+        io.milvus.client.grpc.TopKQueryResultList response;
+
+        try {
+            response = blockingStub.search(request);
+
+            if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                logInfo("Search completed successfully!");
+
+                List<List<SearchResponse.QueryResult>> queryResultsList = getQueryResultsList(response);
+                return new SearchResponse(Response.Status.SUCCESS, queryResultsList);
+            } else {
+                logSevere("Search failed");
+                return new SearchResponse(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                                          response.getStatus().getReason(),
+                                          new ArrayList<>());
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("search RPC failed:\n{0}", e.getStatus().toString());
+            return new SearchResponse(Response.Status.RPC_ERROR, e.toString(), new ArrayList<>());
+        }
+    }
+
+    public SearchResponse searchInFiles(@Nonnull SearchInFilesParam searchInFilesParam) {
+
+        SearchParam searchParam = searchInFilesParam.getSearchParam();
+
+        List<io.milvus.client.grpc.RowRecord> queryRowRecordList = getQueryRowRecordList(searchParam);
+
+        List<io.milvus.client.grpc.Range> queryRangeList = getQueryRangeList(searchParam);
+
+        io.milvus.client.grpc.SearchParam searchParamToSet = io.milvus.client.grpc.SearchParam
+                                                             .newBuilder()
+                                                             .setTableName(searchParam.getTableName())
+                                                             .addAllQueryRecordArray(queryRowRecordList)
+                                                             .addAllQueryRangeArray(queryRangeList)
+                                                             .setTopk(searchParam.getTopK())
+                                                             .setNprobe(searchParam.getNProbe())
+                                                             .build();
+
+        io.milvus.client.grpc.SearchInFilesParam request = io.milvus.client.grpc.SearchInFilesParam
+                                                           .newBuilder()
+                                                           .addAllFileIdArray(searchInFilesParam.getFileIds())
+                                                           .setSearchParam(searchParamToSet)
+                                                           .build();
+
+        io.milvus.client.grpc.TopKQueryResultList response;
+
+        try {
+            response = blockingStub.searchInFiles(request);
+
+            if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                logInfo("Search in files {0} completed successfully!", searchInFilesParam.getFileIds());
+
+                List<List<SearchResponse.QueryResult>> queryResultsList = getQueryResultsList(response);
+                return new SearchResponse(Response.Status.SUCCESS, queryResultsList);
+            } else {
+                logSevere("Search in files {0} failed", searchInFilesParam.getFileIds());
+                return new SearchResponse(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                                          response.getStatus().getReason(),
+                                          new ArrayList<>());
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("searchInFiles RPC failed:\n{0}", e.getStatus().toString());
+            return new SearchResponse(Response.Status.RPC_ERROR, e.toString(), new ArrayList<>());
+        }
+    }
+
+    public DescribeTableResponse describeTable(@Nonnull String tableName) {
+        io.milvus.client.grpc.TableName request = io.milvus.client.grpc.TableName
+                                                  .newBuilder()
+                                                  .setTableName(tableName)
+                                                  .build();
+        io.milvus.client.grpc.TableSchema response;
+
+        try {
+            response = blockingStub.describeTable(request);
+
+            if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                TableSchema tableSchema = new TableSchema.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(Response.Status.SUCCESS, tableSchema);
+            } else {
+                logSevere("Describe Table `{0}` failed:\n{1}", tableName, response.toString());
+                return new DescribeTableResponse(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(Response.Status.RPC_ERROR, e.toString(), null);
+        }
+    }
+
+    public CountTableResponse countTable(@Nonnull String tableName) {
+        io.milvus.client.grpc.TableName request = io.milvus.client.grpc.TableName
+                                                  .newBuilder()
+                                                  .setTableName(tableName)
+                                                  .build();
+        io.milvus.client.grpc.TableRowCount response;
+
+        try {
+            response = blockingStub.countTable(request);
+
+            if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                long tableRowCount = response.getTableRowCount();
+                logInfo("Table `{0}` has {1} rows", tableName, tableRowCount);
+                return new CountTableResponse(Response.Status.SUCCESS, tableRowCount);
+            } else {
+                logSevere("Count Table `{0}` failed:\n{1}", tableName, response.toString());
+                return new CountTableResponse(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                                              response.getStatus().getReason(),
+                                              0);
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("countTable RPC failed:\n{0}", e.getStatus().toString());
+            return new CountTableResponse(Response.Status.RPC_ERROR, e.toString(), 0);
+        }
+    }
+
+    public ShowTablesResponse showTables() {
+        io.milvus.client.grpc.Command request = io.milvus.client.grpc.Command
+                                                .newBuilder()
+                                                .setCmd("")
+                                                .build();
+        io.milvus.client.grpc.TableNameList response;
+
+        try {
+            response = blockingStub.showTables(request);
+
+            if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                List<String> tableNames = response.getTableNamesList();
+                logInfo("Current tables: {0}", tableNames.toString());
+                return new ShowTablesResponse(Response.Status.SUCCESS, tableNames);
+            } else {
+                logSevere("Show tables failed:\n{1}", response.toString());
+                return new ShowTablesResponse(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(Response.Status.RPC_ERROR, e.toString(), new ArrayList<>());
+        }
+    }
+
+    //Cmd(Command) not implemented
+
+    public Response deleteByRange(DeleteByRangeParam deleteByRangeParam) {
+        io.milvus.client.grpc.DeleteByRangeParam request = io.milvus.client.grpc.DeleteByRangeParam
+                                                           .newBuilder()
+                                                           .setRange(getRange(deleteByRangeParam.getDateRange()))
+                                                           .setTableName(deleteByRangeParam.getTableName())
+                                                           .build();
+        io.milvus.client.grpc.Status response;
+
+        try {
+            response = blockingStub.deleteByRange(request);
+
+            if (response.getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                logInfo("Deleted vectors from table `{0}` in range {1} successfully!",
+                             deleteByRangeParam.getTableName(), deleteByRangeParam.getDateRange().toString());
+                return new Response(Response.Status.SUCCESS);
+            } else {
+                logSevere("Deleted vectors from table `{0}` in range {1} failed:\n{1}", response.toString());
+                return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("deleteByRange RPC failed:\n{0}", e.getStatus().toString());
+            return new Response(Response.Status.RPC_ERROR, e.toString());
+        }
+    }
+
+    public Response preloadTable(String tableName) {
+        io.milvus.client.grpc.TableName request = io.milvus.client.grpc.TableName
+                                                 .newBuilder()
+                                                 .setTableName(tableName)
+                                                 .build();
+        io.milvus.client.grpc.Status response;
+
+        try {
+            response = blockingStub.preloadTable(request);
+
+            if (response.getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                logInfo("Preloaded table `{0}` successfully!", tableName);
+                return new Response(Response.Status.SUCCESS);
+            } else {
+                logSevere("Preload table `{0}` failed:\n{1}", tableName, response.toString());
+                return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("preloadTable RPC failed:\n{0}", e.getStatus().toString());
+            return new Response(Response.Status.RPC_ERROR, e.toString());
+        }
+    }
+
+    public DescribeIndexResponse describeIndex(@Nonnull String tableName) {
+        io.milvus.client.grpc.TableName request = io.milvus.client.grpc.TableName
+                                                  .newBuilder()
+                                                  .setTableName(tableName)
+                                                  .build();
+        io.milvus.client.grpc.IndexParam response;
+
+        try {
+            response = blockingStub.describeIndex(request);
+
+            if (response.getStatus().getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                Index index = new Index.Builder()
+                                       .withIndexType(IndexType.valueOf(response.getIndex().getIndexType()))
+                                       .withNList(response.getIndex().getNlist())
+                                       .build();
+                IndexParam indexParam = new IndexParam.Builder(response.getTableName())
+                                                      .withIndex(index)
+                                                      .build();
+                logInfo("Describe index for table `{0}` returned:\n{1}", tableName, indexParam);
+                return new DescribeIndexResponse(Response.Status.SUCCESS, indexParam);
+            } else {
+                logSevere("Describe index for table `{0}` failed:\n{1}", tableName, response.toString());
+                return new DescribeIndexResponse(Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
+                                                response.getStatus().getReason(),
+                                                null);
             }
         } catch (StatusRuntimeException e) {
-            logSevere("Insert RPC failed: {0}", e.getStatus().toString());
-            return Pair.with(new Response(Response.Status.RPC_ERROR, e.toString()), Optional.empty());
+            logSevere("describeIndex RPC failed:\n{0}", e.getStatus().toString());
+            return new DescribeIndexResponse(Response.Status.RPC_ERROR, e.toString(), null);
         }
     }
 
     /////////////////////Util Functions/////////////////////
+    private List<io.milvus.client.grpc.RowRecord> getQueryRowRecordList(@Nonnull SearchParam searchParam) {
+        List<io.milvus.client.grpc.RowRecord> queryRowRecordList = new ArrayList<>();
+        for (List<Float> vectors : searchParam.getQueryVectors()) {
+            io.milvus.client.grpc.RowRecord rowRecord = io.milvus.client.grpc.RowRecord
+                    .newBuilder()
+                    .addAllVectorData(vectors)
+                    .build();
+            queryRowRecordList.add(rowRecord);
+        }
+        return queryRowRecordList;
+    }
+
+    private List<io.milvus.client.grpc.Range> getQueryRangeList(@Nonnull SearchParam searchParam) {
+        List<io.milvus.client.grpc.Range> queryRangeList = new ArrayList<>();
+        String datePattern = "yyyy-MM-dd";
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
+        for (DateRange queryRange : searchParam.getQueryRanges()) {
+            io.milvus.client.grpc.Range dateRange = io.milvus.client.grpc.Range
+                    .newBuilder()
+                    .setStartValue(simpleDateFormat.format(queryRange.getStartDate()))
+                    .setEndValue(simpleDateFormat.format(queryRange.getEndDate()))
+                    .build();
+            queryRangeList.add(dateRange);
+        }
+        return queryRangeList;
+    }
+
+    private io.milvus.client.grpc.Range getRange(@Nonnull DateRange dateRange) {
+        String datePattern = "yyyy-MM-dd";
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
+        return io.milvus.client.grpc.Range
+                .newBuilder()
+                .setStartValue(simpleDateFormat.format(dateRange.getStartDate()))
+                .setEndValue(simpleDateFormat.format(dateRange.getEndDate()))
+                .build();
+    }
+
+    private List<List<SearchResponse.QueryResult>> getQueryResultsList
+            (io.milvus.client.grpc.TopKQueryResultList searchResponse) {
+        //TODO: refactor
+        List<List<SearchResponse.QueryResult>> queryResultsList = new ArrayList<>();
+        Optional<List<io.milvus.client.grpc.TopKQueryResult>> topKQueryResultList
+                = Optional.ofNullable(searchResponse.getTopkQueryResultList());
+        if (topKQueryResultList.isPresent()) {
+            for (io.milvus.client.grpc.TopKQueryResult topKQueryResult : topKQueryResultList.get()) {
+                List<SearchResponse.QueryResult> responseQueryResults = new ArrayList<>();
+                List<io.milvus.client.grpc.QueryResult> queryResults = topKQueryResult.getQueryResultArraysList();
+                for (io.milvus.client.grpc.QueryResult queryResult : queryResults) {
+                    SearchResponse.QueryResult responseQueryResult
+                            = new SearchResponse.QueryResult(queryResult.getId(), queryResult.getDistance());
+                    responseQueryResults.add(responseQueryResult);
+                }
+                queryResultsList.add(responseQueryResults);
+            }
+        }
+        return queryResultsList;
+    }
 
-    public static final String ANSI_RESET = "\u001B[0m";
-    public static final String ANSI_BLACK = "\u001B[30m";
-    public static final String ANSI_RED = "\u001B[31m";
-    public static final String ANSI_GREEN = "\u001B[32m";
-    public static final String ANSI_YELLOW = "\u001B[33m";
-    public static final String ANSI_BLUE = "\u001B[34m";
-    public static final String ANSI_PURPLE = "\u001B[35m";
-    public static final String ANSI_CYAN = "\u001B[36m";
-    public static final String ANSI_WHITE = "\u001B[37m";
+    public Response dropIndex(@Nonnull String tableName) {
+        io.milvus.client.grpc.TableName request = io.milvus.client.grpc.TableName
+                                                  .newBuilder()
+                                                  .setTableName(tableName)
+                                                  .build();
+        io.milvus.client.grpc.Status response;
+
+        try {
+            response = blockingStub.dropIndex(request);
+
+            if (response.getErrorCode() == io.milvus.client.grpc.ErrorCode.SUCCESS) {
+                logInfo("Dropped index for table `{0}` successfully!", tableName);
+                return new Response(Response.Status.SUCCESS);
+            } else {
+                logSevere("Drop index for table `{0}` failed", tableName);
+                return new Response(Response.Status.valueOf(response.getErrorCodeValue()), response.getReason());
+            }
+        } catch (StatusRuntimeException e) {
+            logSevere("dropIndex RPC failed:\n{0}", e.getStatus().toString());
+            return new Response(Response.Status.RPC_ERROR, e.toString());
+        }
+    }
+
+    /////////////////////Log Functions//////////////////////
+
+    private static final String ANSI_RESET = "\u001B[0m";
+    private static final String ANSI_BLACK = "\u001B[30m";
+    private static final String ANSI_RED = "\u001B[31m";
+    private static final String ANSI_GREEN = "\u001B[32m";
+    private static final String ANSI_YELLOW = "\u001B[33m";
+    private static final String ANSI_BLUE = "\u001B[34m";
+    private static final String ANSI_PURPLE = "\u001B[35m";
+    private static final String ANSI_CYAN = "\u001B[36m";
+    private static final String ANSI_WHITE = "\u001B[37m";
+
+    private static final String ANSI_BRIGHT_BLACK  = "\u001B[90m";
+    private static final String ANSI_BRIGHT_RED    = "\u001B[91m";
+    private static final String ANSI_BRIGHT_GREEN  = "\u001B[92m";
+    private static final String ANSI_BRIGHT_YELLOW = "\u001B[93m";
+    private static final String ANSI_BRIGHT_BLUE   = "\u001B[94m";
+    private static final String ANSI_BRIGHT_PURPLE = "\u001B[95m";
+    private static final String ANSI_BRIGHT_CYAN   = "\u001B[96m";
+    private static final String ANSI_BRIGHT_WHITE  = "\u001B[97m";
 
     private void logInfo(String msg, Object... params) {
-        logger.log(Level.INFO, ANSI_GREEN + msg + ANSI_RESET, params);
+        logger.log(Level.INFO, ANSI_YELLOW + msg + ANSI_RESET, params);
     }
 
     private void logWarning(String msg, Object... params) {
-        logger.log(Level.WARNING, ANSI_YELLOW + msg + ANSI_RESET, params);
+        logger.log(Level.WARNING, ANSI_PURPLE + msg + ANSI_RESET, params);
     }
 
     private void logSevere(String msg, Object... params) {
-        logger.log(Level.SEVERE, ANSI_PURPLE + msg + ANSI_RESET, params);
+        logger.log(Level.SEVERE, ANSI_BRIGHT_PURPLE + msg + ANSI_RESET, params);
     }
 
     //////////////////////////Main///////////////////////////
@@ -219,13 +556,14 @@ public class MilvusGrpcClient {
             String tableName = "test_zhiru";
             long dimension = 128;
             TableSchema tableSchema = new TableSchema.Builder(tableName, dimension)
-                                                               .setIndexFileSize(1024)
-                                                               .setMetricType(MetricType.L2)
+                                                               .withIndexFileSize(1024)
+                                                               .withMetricType(MetricType.L2)
                                                                .build();
             Response createTableResponse = client.createTable(tableSchema);
             System.out.println(createTableResponse);
 
-            boolean hasTableResponse = client.hasTable(tableName);
+            HasTableResponse hasTableResponse = client.hasTable(tableName);
+            System.out.println(hasTableResponse);
 
             Random random = new Random();
             List<List<Float>> vectors = new ArrayList<>();
@@ -238,19 +576,66 @@ public class MilvusGrpcClient {
                 vectors.add(vector);
             }
             InsertParam insertParam = new InsertParam.Builder(tableName, vectors).build();
-            Pair<Response, Optional<List<Long>>> insertResult = client.insert(insertParam);
-            System.out.println(insertResult.getValue0());
+            InsertResponse insertResponse = client.insert(insertParam);
+            System.out.println(insertResponse);
 
             Index index = new Index.Builder()
-                                   .setIndexType(IndexType.IVF_SQ8)
-                                   .setNList(16384)
+                                   .withIndexType(IndexType.IVF_SQ8)
+                                   .withNList(16384)
                                    .build();
             IndexParam indexParam = new IndexParam.Builder(tableName)
-                                                  .setIndex(index)
+                                                  .withIndex(index)
                                                   .build();
             Response createIndexResponse = client.createIndex(indexParam);
             System.out.println(createIndexResponse);
 
+            List<List<Float>> vectorsToSearch = new ArrayList<>();
+            vectorsToSearch.add(vectors.get(0));
+            List<DateRange> queryRanges = new ArrayList<>();
+            Date startDate = new Calendar.Builder().setDate(2019, 8, 27).build().getTime();
+            Date endDate = new Calendar.Builder().setDate(2019, 8, 29).build().getTime();
+            queryRanges.add(new DateRange(startDate, endDate));
+            SearchParam searchParam = new SearchParam
+                                         .Builder(tableName, vectorsToSearch)
+                                         .withTopK(100)
+                                         .withNProbe(20)
+                                         .withDateRanges(queryRanges)
+                                         .build();
+            SearchResponse searchResponse = client.search(searchParam);
+            System.out.println(searchResponse);
+
+            List<String> fileIds = new ArrayList<>();
+            fileIds.add("0");
+            SearchInFilesParam searchInFilesParam = new SearchInFilesParam.Builder(fileIds, searchParam).build();
+            searchResponse = client.searchInFiles(searchInFilesParam);
+            System.out.println(searchResponse);
+
+            DescribeTableResponse describeTableResponse = client.describeTable(tableName);
+            describeTableResponse.getTableSchema().ifPresent(System.out::println);
+
+            CountTableResponse countTableResponse = client.countTable(tableName);
+            System.out.println(countTableResponse);
+
+            ShowTablesResponse showTablesResponse = client.showTables();
+            System.out.println(showTablesResponse);
+
+            DeleteByRangeParam deleteByRangeParam = new DeleteByRangeParam.Builder(
+                                                        new DateRange(startDate, endDate), tableName).build();
+            Response deleteByRangeResponse = client.deleteByRange(deleteByRangeParam);
+            System.out.println(deleteByRangeResponse);
+
+            Response preloadTableResponse = client.preloadTable(tableName);
+            System.out.println(preloadTableResponse);
+
+            DescribeIndexResponse describeIndexResponse = client.describeIndex(tableName);
+            describeIndexResponse.getIndexParam().ifPresent(System.out::println);
+
+            Response dropIndexResponse = client.dropIndex(tableName);
+            System.out.println(dropIndexResponse);
+
+            Response dropTableResponse = client.dropTable(tableName);
+            System.out.println(dropTableResponse);
+
         } finally {
             client.shutdown();
         }

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

@@ -0,0 +1,36 @@
+package io.milvus.client.params;
+
+import java.util.Date;
+
+public class DateRange {
+    private Date startDate;
+    private Date endDate;
+
+    public DateRange(Date startDate, Date endDate) {
+        this.startDate = startDate;
+        this.endDate = endDate;
+    }
+
+    public void setStartDate(Date startDate) {
+        this.startDate = startDate;
+    }
+
+    public void setEndDate(Date endDate) {
+        this.endDate = endDate;
+    }
+
+    public Date getStartDate() {
+        return startDate;
+    }
+
+    public Date getEndDate() {
+        return endDate;
+    }
+
+    @Override
+    public String toString() {
+        return "{startDate=" + startDate +
+                ", endDate=" + endDate +
+                '}';
+    }
+}

+ 44 - 0
src/main/java/io/milvus/client/params/DeleteByRangeParam.java

@@ -0,0 +1,44 @@
+package io.milvus.client.params;
+
+import javax.annotation.Nonnull;
+
+public class DeleteByRangeParam {
+    private final DateRange dateRange;
+    private final String tableName;
+
+    public static final class Builder {
+        // Required parameters
+        private final DateRange dateRange;
+        private final String tableName;
+
+        public Builder(DateRange dateRange, String tableName) {
+            this.dateRange = dateRange;
+            this.tableName = tableName;
+        }
+
+        public DeleteByRangeParam build() {
+            return new DeleteByRangeParam(this);
+        }
+    }
+
+    private DeleteByRangeParam(@Nonnull Builder builder) {
+        this.dateRange = builder.dateRange;
+        this.tableName = builder.tableName;
+    }
+
+    public DateRange getDateRange() {
+        return dateRange;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    @Override
+    public String toString() {
+        return "DeleteByRangeParam {" +
+                "dateRange=" + dateRange +
+                ", tableName='" + tableName + '\'' +
+                '}';
+    }
+}

+ 8 - 6
src/main/java/io/milvus/client/params/Index.java

@@ -1,5 +1,7 @@
 package io.milvus.client.params;
 
+import javax.annotation.Nonnull;
+
 public class Index {
     private final IndexType indexType;
     private final int nList;
@@ -9,13 +11,13 @@ public class Index {
         private IndexType indexType = IndexType.FLAT;
         private int nList = 16384;
 
-        public Builder setIndexType(IndexType val) {
-            indexType = val;
+        public Builder withIndexType(IndexType indexType) {
+            this.indexType = indexType;
             return this;
         }
 
-        public Builder setNList(int val) {
-            nList = val;
+        public Builder withNList(int nList) {
+            this.nList = nList;
             return this;
         }
 
@@ -24,7 +26,7 @@ public class Index {
         }
     }
 
-    private Index(Builder builder) {
+    private Index(@Nonnull Builder builder) {
         this.indexType = builder.indexType;
         this.nList = builder.nList;
     }
@@ -33,7 +35,7 @@ public class Index {
         return indexType;
     }
 
-    public int getnNList() {
+    public int getNList() {
         return nList;
     }
 }

+ 7 - 5
src/main/java/io/milvus/client/params/IndexParam.java

@@ -1,5 +1,7 @@
 package io.milvus.client.params;
 
+import javax.annotation.Nonnull;
+
 public class IndexParam {
 
     private final String tableName;
@@ -16,8 +18,8 @@ public class IndexParam {
             this.tableName = tableName;
         }
 
-        public Builder setIndex(Index indexToSet) {
-            index = indexToSet;
+        public Builder withIndex(Index index) {
+            this.index = index;
             return this;
         }
 
@@ -26,7 +28,7 @@ public class IndexParam {
         }
     }
 
-    private IndexParam(Builder builder) {
+    private IndexParam(@Nonnull Builder builder) {
         this.tableName = builder.tableName;
         this.index = builder.index;
     }
@@ -41,7 +43,7 @@ public class IndexParam {
 
     @Override
     public String toString() {
-        return String.format("IndexParam {tableName = %s, index = {indexType = %s, nList = %d}",
-                                tableName, index.getIndexType().name(), index.getnNList());
+        return String.format("IndexParam = {tableName = %s, index = {indexType = %s, nList = %d}",
+                                tableName, index.getIndexType().name(), index.getNList());
     }
 }

+ 17 - 5
src/main/java/io/milvus/client/params/IndexType.java

@@ -1,20 +1,32 @@
 package io.milvus.client.params;
 
+import java.util.Arrays;
+import java.util.Optional;
+
 public enum IndexType {
 
     INVALID(0),
     FLAT(1),
     IVFLAT(2),
     IVF_SQ8(3),
-    MIX_NSG(4);
+    MIX_NSG(4),
+
+    UNKNOWN(-1);
 
-    private final int indexType;
+    private final int val;
 
-    IndexType(int indexType) {
-        this.indexType = indexType;
+    IndexType(int val) {
+        this.val = val;
     }
 
     public int getVal() {
-        return indexType;
+        return val;
+    }
+
+    public static IndexType valueOf(int val) {
+        Optional<IndexType> search = Arrays.stream(values())
+                                           .filter(indexType -> indexType.val == val)
+                                           .findFirst();
+        return search.orElse(UNKNOWN);
     }
 }

+ 4 - 3
src/main/java/io/milvus/client/params/InsertParam.java

@@ -1,5 +1,6 @@
 package io.milvus.client.params;
 
+import javax.annotation.Nonnull;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -21,8 +22,8 @@ public class InsertParam {
             this.vectors = vectors;
         }
 
-        public Builder setVectorIds(List<Long> val) {
-            vectorIds = val;
+        public Builder withVectorIds(List<Long> vectorIds) {
+            this.vectorIds = vectorIds;
             return this;
         }
 
@@ -31,7 +32,7 @@ public class InsertParam {
         }
     }
 
-    private InsertParam(Builder builder) {
+    private InsertParam(@Nonnull Builder builder) {
         this.tableName = builder.tableName;
         this.vectors = builder.vectors;
         this.vectorIds = builder.vectorIds;

+ 17 - 5
src/main/java/io/milvus/client/params/MetricType.java

@@ -1,16 +1,28 @@
 package io.milvus.client.params;
 
+import java.util.Arrays;
+import java.util.Optional;
+
 public enum MetricType {
     L2(1),
-    IP(2);
+    IP(2),
+
+    UNKNOWN(-1);
 
-    private final int metricType;
+    private final int val;
 
-    MetricType(int metricType) {
-        this.metricType = metricType;
+    MetricType(int val) {
+        this.val = val;
     }
 
     public int getVal() {
-        return metricType;
+        return val;
+    }
+
+    public static MetricType valueOf(int val) {
+        Optional<MetricType> search = Arrays.stream(values())
+                                     .filter(metricType -> metricType.val == val)
+                                     .findFirst();
+        return search.orElse(UNKNOWN);
     }
 }

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

@@ -0,0 +1,37 @@
+package io.milvus.client.params;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+
+public class SearchInFilesParam {
+    private final List<String> fileIds;
+    private final SearchParam searchParam;
+
+    public static class Builder {
+        // Required parameters
+        private final List<String> fileIds;
+        private final SearchParam searchParam;
+
+        public Builder(List<String> fileIds, SearchParam searchParam) {
+            this.fileIds = fileIds;
+            this.searchParam = searchParam;
+        }
+
+        public SearchInFilesParam build() {
+            return new SearchInFilesParam(this);
+        }
+    }
+
+    private SearchInFilesParam(@Nonnull Builder builder) {
+        this.fileIds = builder.fileIds;
+        this.searchParam = builder.searchParam;
+    }
+
+    public List<String> getFileIds() {
+        return fileIds;
+    }
+
+    public SearchParam getSearchParam() {
+        return searchParam;
+    }
+}

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

@@ -0,0 +1,78 @@
+package io.milvus.client.params;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class SearchParam {
+
+    private final String tableName;
+    private final List<List<Float>> queryVectors;
+    private final List<DateRange> queryRanges;
+    private final long topK;
+    private final long nProbe;
+
+    public static class Builder {
+        // Required parameters
+        private final String tableName;
+        private final List<List<Float>> queryVectors;
+
+        // Optional parameters - initialized to default values
+        private List<DateRange> queryRanges = new ArrayList<>();
+        private long topK = 1;
+        private long nProbe = 10;
+
+        public Builder(String tableName, List<List<Float>> queryVectors) {
+            this.tableName = tableName;
+            this.queryVectors = queryVectors;
+        }
+
+        public Builder withDateRanges(List<DateRange> queryRanges) {
+            this.queryRanges = queryRanges;
+            return this;
+        }
+
+        public Builder withTopK(long topK) {
+            this.topK = topK;
+            return this;
+        }
+
+        public Builder withNProbe(long nProbe) {
+            this.nProbe = nProbe;
+            return this;
+        }
+
+        public SearchParam build() {
+            return new SearchParam(this);
+        }
+    }
+
+    private SearchParam(@Nonnull Builder builder) {
+        this.tableName = builder.tableName;
+        this.queryVectors = builder.queryVectors;
+        this.queryRanges = builder.queryRanges;
+        this.nProbe = builder.nProbe;
+        this.topK = builder.topK;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public List<List<Float>> getQueryVectors() {
+        return queryVectors;
+    }
+
+    public List<DateRange> getQueryRanges() {
+        return queryRanges;
+    }
+
+    public long getTopK() {
+        return topK;
+    }
+
+    public long getNProbe() {
+        return nProbe;
+    }
+}

+ 5 - 5
src/main/java/io/milvus/client/params/TableSchema.java

@@ -23,12 +23,12 @@ public class TableSchema {
             this.dimension = dimension;
         }
 
-        public Builder setIndexFileSize(long val) {
-            indexFileSize = val;
+        public Builder withIndexFileSize(long indexFileSize) {
+            this.indexFileSize = indexFileSize;
             return this;
         }
-        public Builder setMetricType(MetricType val) {
-            metricType = val;
+        public Builder withMetricType(MetricType metricType) {
+            this.metricType = metricType;
             return this;
         }
 
@@ -62,7 +62,7 @@ public class TableSchema {
 
     @Override
     public String toString() {
-        return String.format("TableSchema {tableName = %s, dimension = %d, indexFileSize = %d, metricType = %s}",
+        return String.format("TableSchema = {tableName = %s, dimension = %d, indexFileSize = %d, metricType = %s}",
                              tableName, dimension, indexFileSize, metricType.name());
     }
 }

+ 26 - 0
src/main/java/io/milvus/client/response/CountTableResponse.java

@@ -0,0 +1,26 @@
+package io.milvus.client.response;
+
+public class CountTableResponse extends Response {
+    private final long tableRowCount;
+
+    public CountTableResponse(Status status, String message, long tableRowCount) {
+        super(status, message);
+        this.tableRowCount = tableRowCount;
+    }
+
+    public CountTableResponse(Status status, long tableRowCount) {
+        super(status);
+        this.tableRowCount = tableRowCount;
+    }
+
+    public long getTableRowCount() {
+        return tableRowCount;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("CountTableResponse {code = %s, message = %s, table row count = %d}",
+                              this.getStatus(), this.getMessage(),
+                              tableRowCount);
+    }
+}

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

@@ -0,0 +1,30 @@
+package io.milvus.client.response;
+
+import io.milvus.client.params.IndexParam;
+
+import javax.annotation.Nullable;
+import java.util.Optional;
+
+public class DescribeIndexResponse extends Response {
+    private final IndexParam indexParam;
+
+    public DescribeIndexResponse(Status status, String message, @Nullable IndexParam indexParam) {
+        super(status, message);
+        this.indexParam = indexParam;
+    }
+
+    public DescribeIndexResponse(Status status, @Nullable IndexParam indexParam) {
+        super(status);
+        this.indexParam = indexParam;
+    }
+
+    public Optional<IndexParam> getIndexParam() {
+        return Optional.ofNullable(indexParam);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DescribeIndexResponse {code = %s, message = %s, %s}", this.getStatus(), this.getMessage(),
+                              indexParam == null ? "Index param = None" : indexParam.toString());
+    }
+}

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

@@ -0,0 +1,30 @@
+package io.milvus.client.response;
+
+import io.milvus.client.params.TableSchema;
+
+import javax.annotation.Nullable;
+import java.util.Optional;
+
+public class DescribeTableResponse extends Response {
+    private final TableSchema tableSchema;
+
+    public DescribeTableResponse(Status status, String message, @Nullable TableSchema tableSchema) {
+        super(status, message);
+        this.tableSchema = tableSchema;
+    }
+
+    public DescribeTableResponse(Status status, @Nullable TableSchema tableSchema) {
+        super(status);
+        this.tableSchema = tableSchema;
+    }
+
+    public Optional<TableSchema> getTableSchema() {
+        return Optional.ofNullable(tableSchema);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("DescribeTableResponse {code = %s, message = %s, %s}", this.getStatus(), this.getMessage(),
+                             tableSchema == null ? "Table schema = None" : tableSchema.toString());
+    }
+}

+ 26 - 0
src/main/java/io/milvus/client/response/HasTableResponse.java

@@ -0,0 +1,26 @@
+package io.milvus.client.response;
+
+public class HasTableResponse extends Response {
+    private final boolean hasTable;
+
+    public HasTableResponse(Status status, String message, boolean hasTable) {
+        super(status, message);
+        this.hasTable = hasTable;
+    }
+
+    public HasTableResponse(Status status, boolean hasTable) {
+        super(status);
+        this.hasTable = hasTable;
+    }
+
+    public boolean hasTable() {
+        return hasTable;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("HasTableResponse {code = %s, message = %s, has table = %s}",
+                              this.getStatus(), this.getMessage(),
+                              hasTable);
+    }
+}

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

@@ -0,0 +1,31 @@
+package io.milvus.client.response;
+
+import java.util.List;
+import java.util.Optional;
+
+public class InsertResponse extends Response {
+
+    private final List<Long> vectorIds;
+
+    public InsertResponse(Status status, String message, List<Long> vectorIds) {
+        super(status, message);
+        this.vectorIds = vectorIds;
+    }
+
+    public InsertResponse(Status status, List<Long> vectorIds) {
+        super(status);
+        this.vectorIds = vectorIds;
+    }
+
+    public List<Long> getVectorIds() {
+        return vectorIds;
+    }
+
+    //TODO: iterator
+
+    @Override
+    public String toString() {
+        return String.format("InsertResponse {code = %s, message = %s, returned %d vector ids}",
+                             this.getStatus().name(), this.getMessage(), this.vectorIds.size());
+    }
+}

+ 4 - 4
src/main/java/io/milvus/client/Response.java → src/main/java/io/milvus/client/response/Response.java

@@ -1,4 +1,4 @@
-package io.milvus.client;
+package io.milvus.client.response;
 
 import java.util.Arrays;
 import java.util.Optional;
@@ -57,12 +57,12 @@ public class Response {
     private final Status status;
     private final String message;
 
-    Response(Status status, String message) {
+    public Response(Status status, String message) {
         this.status = status;
         this.message = message;
     }
 
-    Response(Status status) {
+    public Response(Status status) {
         this.status = status;
         this.message = "Success!";
     }
@@ -81,6 +81,6 @@ public class Response {
 
     @Override
     public String toString() {
-        return String.format("{code = %s, message = %s}", status.name(), this.message);
+        return String.format("Response {code = %s, message = %s}", status.name(), this.message);
     }
 }

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

@@ -0,0 +1,49 @@
+package io.milvus.client.response;
+
+import java.util.List;
+import java.util.Optional;
+
+public class SearchResponse extends Response {
+
+    public static class QueryResult {
+        private final long vectorId;
+        private final double distance;
+
+        public QueryResult(long vectorId, double distance) {
+            this.vectorId = vectorId;
+            this.distance = distance;
+        }
+
+        public long getVectorId() {
+            return vectorId;
+        }
+
+        public double getDistance() {
+            return distance;
+        }
+    }
+
+    private final List<List<QueryResult>> queryResultsList;
+
+    public SearchResponse(Status status, String message, List<List<QueryResult>> queryResultsList) {
+        super(status, message);
+        this.queryResultsList = queryResultsList;
+    }
+
+    public SearchResponse(Status status, List<List<QueryResult>> queryResultsList) {
+        super(status);
+        this.queryResultsList = queryResultsList;
+    }
+
+    public List<List<QueryResult>> getQueryResultsList() {
+        return queryResultsList;
+    }
+
+    //TODO: iterator
+
+    @Override
+    public String toString() {
+        return String.format("SearchResponse {code = %s, message = %s, returned results for %d queries}",
+                this.getStatus().name(), this.getMessage(), this.queryResultsList.size());
+    }
+}

+ 28 - 0
src/main/java/io/milvus/client/response/ShowTablesResponse.java

@@ -0,0 +1,28 @@
+package io.milvus.client.response;
+
+import java.util.List;
+
+public class ShowTablesResponse extends Response {
+    private final List<String> tableNames;
+
+    public ShowTablesResponse(Status status, String message, List<String> tableNames) {
+        super(status, message);
+        this.tableNames = tableNames;
+    }
+
+    public ShowTablesResponse(Status status, List<String> tableNames) {
+        super(status);
+        this.tableNames = tableNames;
+    }
+
+    public List<String> getTableNames() {
+        return tableNames;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ShowTablesResponse {code = %s, message = %s, table names = %s}",
+                              this.getStatus(), this.getMessage(),
+                              tableNames.toString());
+    }
+}