Selaa lähdekoodia

Support basic DDL Operations (#200)

* fix pom error (#175)

Signed-off-by: yhmo <yihua.mo@zilliz.com>
Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* Change master branch to Milvus 2.0, bring in protos (#190)

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* framework && simple connection

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* pass in exception message in R

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* pass in exception message in R

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* pass in exception message in R

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* add insert and delete

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

* add search

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>
(cherry picked from commit c263ca984be096c57ae628c7b22dd9635e4598d2)

* add search

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

(cherry picked from commit e50b063cc405496e801ee3b61e8a65882214d47a)

* add query and caldistance

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

(cherry picked from commit dbf2a4b9b1a88fef4662ad73be7501ccd6cec5d1)

* process magic value

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>
(cherry picked from commit 880176bcd86e9f79ab26214f2a28ea92419cda75)

* adjust frame

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>

(cherry picked from commit 9fe3141fad97afc347d946cd06a710f55069c88a)

* adjust frame

Signed-off-by: luhongwei <hongweilu@sohu-inc.com>
(cherry picked from commit 19143c26e69c41ef86924e58e1f0c0aa24d2d1a8)

Co-authored-by: groot <yihua.mo@zilliz.com>
Co-authored-by: Xiaofan <83447078+xiaofan-luan@users.noreply.github.com>
Co-authored-by: luhongwei <hongweilu@sohu-inc.com>
trovwu 3 vuotta sitten
vanhempi
commit
d1dbab77bc

+ 0 - 0
examples/main/src/io/milvus/DDLExample.java → examples/main/io/milvus/DDLExample.java


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

@@ -0,0 +1,128 @@
+package io.milvus;
+
+import com.google.protobuf.ByteString;
+import io.milvus.client.MilvusServiceClient;
+import io.milvus.grpc.*;
+import io.milvus.param.*;
+import io.milvus.param.dml.*;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+
+public class DMLExample {
+
+    public static MilvusServiceClient milvusClient;
+
+    //vector1
+    List<Float> vector1 = Arrays.asList(101f, 103f, 107f, 108f);
+    // vector2
+    List<Float> vector2 = Arrays.asList(111f, 112f, 113f, 114f);
+
+    static {
+        ConnectParam connectParam = ConnectParam.Builder.newBuilder()
+                .withHost("localhost")
+                .withPort(19530)
+                .build();
+        milvusClient = new MilvusServiceClient(connectParam);
+    }
+
+    @Test
+    public void insert() {
+        // save two vectors : id=101,value=[101,103,107,108] ; id=102,value=[111,112,113,114]
+        // primary field's name is xp , vector field name is vector
+        // collection name is test
+
+        String collectionName = "test";
+        String partitionName = "pT";
+
+        List<String> fieldNames = Arrays.asList("xp", "vector");
+        List<DataType> dataTypes = Arrays.asList(DataType.Int64, DataType.FloatVector);
+
+        // primaryKey ids
+        List<Long> ids = Arrays.asList(101L, 102L);
+
+        // vectors' list
+        List<List<Float>> vectors = new ArrayList<>();
+
+        vectors.add(vector1);
+        vectors.add(vector2);
+
+        // fieldValues; for ids, <?> is Long; for vectors <?> is List<Float>
+        List<List<?>> result = new ArrayList<>();
+        result.add(ids);
+        result.add(vectors);
+
+        InsertParam insertParam = InsertParam.Builder
+                .nweBuilder(collectionName)
+                .setFieldNum(fieldNames.size())
+                .setFieldNames(fieldNames)
+                .setPartitionName(partitionName)
+                .setDataTypes(dataTypes)
+                .setFieldValues(result)
+                .build();
+
+        R<MutationResult> insert = milvusClient.insert(insertParam);
+        System.out.println(insert.getData());
+
+
+        R<FlushResponse> flush = milvusClient.flush(collectionName);
+
+        System.out.println(flush.getData());
+    }
+
+    @Test
+    public void delete() {
+        String collectionName = "test";
+        String partitionName = "pT";
+        DeleteParam build = DeleteParam.Builder.nweBuilder()
+                .setCollectionName(collectionName)
+                .setPartitionName(partitionName)
+                .build();
+        R<MutationResult> delete = milvusClient.delete(build);
+        System.out.println(delete.getData());
+    }
+
+    @Test
+    public void search() {
+        String collectionName = "test";
+        String fieldName = "vector";
+        List<String> outFields = Collections.singletonList("xp");
+
+        HashMap<String, String> params = new HashMap<String, String>() {{
+            put("params", "{\"nprobe\":10}");
+        }};
+        SearchParam searchParam = SearchParam.Builder.newBuilder()
+                .setCollectionName(collectionName)
+                .setMetricType(MetricType.L2)
+                .setOutFields(outFields)
+                .setTopK(5)
+                .setVectors(Collections.singletonList(vector1))
+                .setVectorFieldName(fieldName)
+                .setDslType(DslType.BoolExprV1)
+                .setDsl("xp > 100")
+                .setParams(params)
+                .build();
+
+
+        R<SearchResults> search = milvusClient.search(searchParam);
+        System.out.println(search);
+    }
+
+    @Test
+    public void calDistance() {
+        CalcDistanceParam calcDistanceParam = new CalcDistanceParam(vector1, vector2, MetricType.L2);
+        R<CalcDistanceResults> calcDistanceResultsR = milvusClient.calcDistance(calcDistanceParam);
+        System.out.println(calcDistanceResultsR);
+    }
+
+    @Test
+    public void query() {
+        String collectionName = "test";
+        QueryParam test = QueryParam.Builder.newBuilder("xp in [ 101, 102]")
+                .setCollectionName(collectionName)
+                .build();
+        R<QueryResults> query = milvusClient.query(test);
+        System.out.println(query);
+    }
+}

+ 334 - 2
src/main/java/io/milvus/client/AbstractMilvusGrpcClient.java

@@ -1,5 +1,17 @@
 package io.milvus.client;
 
+import com.google.protobuf.ByteString;
+import io.grpc.StatusRuntimeException;
+import io.milvus.exception.ParamException;
+import io.milvus.grpc.*;
+import io.milvus.param.*;
+import io.milvus.param.dml.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.util.stream.Collectors;
 import io.grpc.StatusRuntimeException;
 import io.milvus.grpc.BoolResponse;
 import io.milvus.grpc.CollectionSchema;
@@ -62,8 +74,6 @@ import io.milvus.param.partition.ShowPartitionParam;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -82,6 +92,328 @@ public abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
     protected abstract boolean maybeAvailable();
 
+
+
+    @Override
+    public R<FlushResponse> flush(String collectionName, String dbName) {
+        return flush(Collections.singletonList(collectionName), dbName);
+    }
+
+    @Override
+    public R<FlushResponse> flush(String collectionName) {
+        return flush(Collections.singletonList(collectionName), "");
+
+    }
+
+    @Override
+    public R<FlushResponse> flush(List<String> collectionNames) {
+        return flush(collectionNames, "");
+
+    }
+
+    @Override
+    public R<FlushResponse> flush(List<String> collectionNames, String dbName) {
+        MsgBase msgBase = MsgBase.newBuilder().setMsgType(MsgType.Flush).build();
+        FlushRequest.Builder builder = FlushRequest.newBuilder().setBase(msgBase).setDbName(dbName);
+        collectionNames.forEach(builder::addCollectionNames);
+        FlushRequest flushRequest = builder.build();
+        FlushResponse flush = null;
+        try {
+            flush = blockingStub().flush(flushRequest);
+        } catch (Exception e) {
+            return R.failed(e);
+        }
+        return R.success(flush);
+    }
+
+    @Override
+    public R<MutationResult> delete(DeleteParam deleteParam) {
+
+        DeleteRequest deleteRequest = DeleteRequest.newBuilder()
+                .setBase(MsgBase.newBuilder().setMsgType(MsgType.Delete).build())
+                .setCollectionName(deleteParam.getCollectionName())
+                .setPartitionName(deleteParam.getPartitionName())
+                .build();
+
+        MutationResult delete = null;
+        try {
+            delete = blockingStub().delete(deleteRequest);
+        } catch (Exception e) {
+            return R.failed(e);
+        }
+        return R.success(delete);
+    }
+
+    @Override
+    public R<MutationResult> insert(InsertParam insertParam) {
+        //check params : two steps
+        // 1、check sdk incoming params
+        String collectionName = insertParam.getCollectionName();
+        String partitionName = insertParam.getPartitionName();
+        int fieldNum = insertParam.getFieldNum();
+        List<String> fieldNames = insertParam.getFieldNames();
+        List<DataType> dataTypes = insertParam.getDataTypes();
+        List<List<?>> fieldValues = insertParam.getFieldValues();
+        Integer filedNameSize = Optional.ofNullable(fieldNames).map(List::size).orElse(0);
+        Integer dTypeSize = Optional.ofNullable(dataTypes).map(List::size).orElse(0);
+        int fieldValueSize = Optional.ofNullable(fieldValues).map(List::size).orElse(0);
+        if (fieldNum != fieldValueSize || fieldNum != filedNameSize || fieldNum != dTypeSize) {
+            throw new ParamException("size is illegal");
+        }
+
+        //2、need to DDL request to get collection meta schema and check vector dim;
+        // whether the collection schema needs to be cached locally todo
+        assert fieldValues != null;
+        int numRow = fieldValues.get(0).size();
+
+        //3、gen insert request
+        MsgBase msgBase = MsgBase.newBuilder().setMsgType(MsgType.Insert).build();
+        InsertRequest.Builder insertBuilder = InsertRequest.newBuilder()
+                .setCollectionName(collectionName)
+                .setPartitionName(partitionName)
+                .setBase(msgBase)
+                .setNumRows(numRow);
+
+        // gen fieldData
+        for (int i = 0; i < fieldNum; i++) {
+            insertBuilder.addFieldsData(genFieldData(fieldNames.get(i), dataTypes.get(i), fieldValues.get(i)));
+        }
+
+        InsertRequest insertRequest = insertBuilder.build();
+        MutationResult insert = null;
+        try {
+            insert = blockingStub().insert(insertRequest);
+        } catch (Exception e) {
+            R.failed(e);
+        }
+        return R.success(insert);
+
+    }
+
+    @Override
+    public R<SearchResults> search(SearchParam searchParam) {
+        SearchRequest.Builder builder = SearchRequest.newBuilder()
+                .setDbName(searchParam.getDbName())
+                .setCollectionName(searchParam.getCollectionName());
+        if (!searchParam.getPartitionNames().isEmpty()) {
+            searchParam.getPartitionNames().forEach(builder::addPartitionNames);
+        }
+
+        List<List<Float>> vectors = searchParam.getVectors();
+        List<ByteString> byteStrings = vectors.stream().map(vector -> {
+            ByteBuffer allocate1 = ByteBuffer.allocate(16);
+            vector.forEach(allocate1::putFloat);
+            byte[] array = allocate1.array();
+            return ByteString.copyFrom(array);
+        }).collect(Collectors.toList());
+
+
+        PlaceholderValue.Builder pldBuilder = PlaceholderValue.newBuilder()
+                .setTag(Constant.vectorTag)
+                .setType(PlaceholderType.FloatVector);
+        byteStrings.forEach(pldBuilder::addValues);
+
+        PlaceholderGroup placeholderGroup = PlaceholderGroup.newBuilder()
+                .addPlaceholders(pldBuilder.build())
+                .build();
+
+        builder.setPlaceholderGroup(placeholderGroup.toByteString());
+
+        builder.addSearchParams(
+                        KeyValuePair.newBuilder()
+                                .setKey(Constant.vectorFiled)
+                                .setValue(searchParam.getVectorFieldName())
+                                .build())
+                .addSearchParams(
+                        KeyValuePair.newBuilder()
+                                .setKey(Constant.topK)
+                                .setValue(String.valueOf(searchParam.getTopK()))
+                                .build())
+                .addSearchParams(
+                        KeyValuePair.newBuilder()
+                                .setKey(Constant.metricType)
+                                .setValue(searchParam.getMetricType().name())
+                                .build());
+
+        if (!searchParam.getParams().isEmpty() && null != searchParam.getParams().get(Constant.parmas)
+                && !searchParam.getParams().get(Constant.parmas).isEmpty()) {
+            builder.addSearchParams(
+                    KeyValuePair.newBuilder()
+                            .setKey(Constant.parmas)
+                            .setValue(searchParam.getParams().get(Constant.parmas))
+                            .build());
+        }
+
+        if (!searchParam.getOutFields().isEmpty()) {
+            searchParam.getOutFields().forEach(builder::addOutputFields);
+        }
+
+        builder.setDslType(searchParam.getDslType());
+        if (searchParam.getDsl() == null || searchParam.getDsl().isEmpty()) {
+            builder.setDsl(searchParam.getDsl());
+        }
+
+        SearchRequest searchRequest = builder.build();
+
+
+        SearchResults search;
+        try {
+            search = this.blockingStub().search(searchRequest);
+        } catch (Exception e) {
+            logger.error("[milvus] search rpc request error:{}", e.getMessage());
+            return R.failed(e);
+        }
+
+        return R.success(search);
+    }
+
+    @Override
+    public R<QueryResults> query(QueryParam queryParam) {
+        QueryRequest queryRequest = QueryRequest.newBuilder()
+                .setDbName(queryParam.getDbName())
+                .setCollectionName(queryParam.getCollectionName())
+                .addAllPartitionNames(queryParam.getPartitionNames())
+                .addAllOutputFields(queryParam.getOutFields())
+                .setExpr(queryParam.getExpr())
+                .build();
+
+        QueryResults query;
+        try {
+            query = this.blockingStub().query(queryRequest);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.failed(e);
+        }
+        return R.success(query);
+    }
+
+    @Override
+    public R<CalcDistanceResults> calcDistance(CalcDistanceParam calcDistanceParam) {
+        List<Float> vector1 = calcDistanceParam.getVector1();
+        List<Float> vector2 = calcDistanceParam.getVector2();
+
+        CalcDistanceRequest calcDistanceRequest = CalcDistanceRequest.newBuilder()
+                .setOpLeft(
+                        VectorsArray.newBuilder()
+                                .setDataArray(
+                                        VectorField.newBuilder()
+                                                .setFloatVector(
+                                                        FloatArray.newBuilder()
+                                                                .addAllData(vector1)
+                                                                .build())
+                                                .setDim(vector1.size())
+                                                .build()
+                                )
+                                .build()
+                )
+                .setOpRight(
+                        VectorsArray.newBuilder()
+                                .setDataArray(
+                                        VectorField.newBuilder()
+                                                .setFloatVector(
+                                                        FloatArray.newBuilder()
+                                                                .addAllData(vector2)
+                                                                .build())
+                                                .setDim(vector2.size())
+                                                .build()
+                                )
+                                .build()
+                )
+                .addParams(
+                        KeyValuePair.newBuilder()
+                                .setKey("metric")
+                                .setValue(calcDistanceParam.getMetricType().name())
+                                .build()
+                )
+                .build();
+        CalcDistanceResults calcDistanceResults;
+        try {
+            calcDistanceResults = blockingStub().calcDistance(calcDistanceRequest);
+        } catch (Exception e) {
+            logger.error("[milvus] calDistance rpc request error:{}", e.getMessage());
+            return R.failed(e);
+        }
+        return R.success(calcDistanceResults);
+    }
+
+    private FieldData genFieldData(String fieldName, DataType dataType, List<?> objects) {
+        if (objects == null) {
+            throw new ParamException("params is null");
+        }
+        FieldData.Builder builder = FieldData.newBuilder();
+        if (vectorDataType.contains(dataType)) {
+            if (dataType == DataType.FloatVector) {
+                List<Float> floats = new ArrayList<>();
+                // 每个object是个list
+                for (Object object : objects) {
+                    if (object instanceof List) {
+                        List list = (List) object;
+                        list.forEach(o -> floats.add((Float) o));
+                    } else {
+                        throw new ParamException("参数有问题");
+                    }
+                }
+                int dim = floats.size() / objects.size();
+                FloatArray floatArray = FloatArray.newBuilder().addAllData(floats).build();
+                VectorField vectorField = VectorField.newBuilder().setDim(dim).setFloatVector(floatArray).build();
+                return builder.setFieldName(fieldName).setType(DataType.FloatVector).setVectors(vectorField).build();
+            } else if (dataType == DataType.BinaryVector) {
+                List<ByteBuffer> bytes = objects.stream().map(p -> (ByteBuffer) p).collect(Collectors.toList());
+                ;
+                ByteString byteString = ByteString.copyFrom((ByteBuffer) bytes);
+                int dim = objects.size();
+                VectorField vectorField = VectorField.newBuilder().setDim(dim).setBinaryVector(byteString).build();
+                return builder.setFieldName(fieldName).setType(DataType.BinaryVector).setVectors(vectorField).build();
+            }
+
+
+        } else {
+            switch (dataType) {
+                case None:
+                case UNRECOGNIZED:
+                    throw new ParamException("not support this dataType:" + dataType);
+                case Int64:
+                case Int32:
+                case Int16:
+                    List<Long> longs = objects.stream().map(p -> (Long) p).collect(Collectors.toList());
+                    LongArray longArray = LongArray.newBuilder().addAllData(longs).build();
+                    ScalarField scalarField1 = ScalarField.newBuilder().setLongData(longArray).build();
+                    return builder.setFieldName(fieldName).setType(dataType).setScalars(scalarField1).build();
+                case Int8:
+                    List<Integer> integers = objects.stream().map(p -> (Integer) p).collect(Collectors.toList());
+                    IntArray intArray = IntArray.newBuilder().addAllData(integers).build();
+                    ScalarField scalarField2 = ScalarField.newBuilder().setIntData(intArray).build();
+                    return builder.setFieldName(fieldName).setType(dataType).setScalars(scalarField2).build();
+                case Bool:
+                    List<Boolean> booleans = objects.stream().map(p -> (Boolean) p).collect(Collectors.toList());
+                    BoolArray boolArray = BoolArray.newBuilder().addAllData(booleans).build();
+                    ScalarField scalarField3 = ScalarField.newBuilder().setBoolData(boolArray).build();
+                    return builder.setFieldName(fieldName).setType(dataType).setScalars(scalarField3).build();
+                case Float:
+                    List<Float> floats = objects.stream().map(p -> (Float) p).collect(Collectors.toList());
+                    FloatArray floatArray = FloatArray.newBuilder().addAllData(floats).build();
+                    ScalarField scalarField4 = ScalarField.newBuilder().setFloatData(floatArray).build();
+                    return builder.setFieldName(fieldName).setType(dataType).setScalars(scalarField4).build();
+                case Double:
+                    List<Double> doubles = objects.stream().map(p -> (Double) p).collect(Collectors.toList());
+                    DoubleArray doubleArray = DoubleArray.newBuilder().addAllData(doubles).build();
+                    ScalarField scalarField5 = ScalarField.newBuilder().setDoubleData(doubleArray).build();
+                    return builder.setFieldName(fieldName).setType(dataType).setScalars(scalarField5).build();
+                case String:
+                    List<String> strings = objects.stream().map(p -> (String) p).collect(Collectors.toList());
+                    StringArray stringArray = StringArray.newBuilder().addAllData(strings).build();
+                    ScalarField scalarField6 = ScalarField.newBuilder().setStringData(stringArray).build();
+                    return builder.setFieldName(fieldName).setType(dataType).setScalars(scalarField6).build();
+            }
+        }
+        return null;
+    }
+
+    private static final Set<DataType> vectorDataType = new HashSet<DataType>() {{
+        add(DataType.FloatVector);
+        add(DataType.BinaryVector);
+    }};
+
     @Override
     public R<Boolean> hasCollection(HasCollectionParam requestParam) {
         if (checkServerConnection()) {

+ 25 - 3
src/main/java/io/milvus/client/MilvusClient.java

@@ -19,6 +19,10 @@
 
 package io.milvus.client;
 
+import io.milvus.grpc.*;
+import io.milvus.param.*;
+
+import java.util.List;
 import io.milvus.grpc.DescribeCollectionResponse;
 import io.milvus.grpc.DescribeIndexResponse;
 import io.milvus.grpc.GetCollectionStatisticsResponse;
@@ -27,7 +31,6 @@ import io.milvus.grpc.GetIndexStateResponse;
 import io.milvus.grpc.GetPartitionStatisticsResponse;
 import io.milvus.grpc.ShowCollectionsResponse;
 import io.milvus.grpc.ShowPartitionsResponse;
-import io.milvus.param.R;
 import io.milvus.param.RpcStatus;
 import io.milvus.param.collection.CreateCollectionParam;
 import io.milvus.param.collection.DescribeCollectionParam;
@@ -37,6 +40,7 @@ import io.milvus.param.collection.HasCollectionParam;
 import io.milvus.param.collection.LoadCollectionParam;
 import io.milvus.param.collection.ReleaseCollectionParam;
 import io.milvus.param.collection.ShowCollectionParam;
+import io.milvus.param.dml.*;
 import io.milvus.param.index.CreateIndexParam;
 import io.milvus.param.index.DescribeIndexParam;
 import io.milvus.param.index.DropIndexParam;
@@ -55,11 +59,29 @@ import java.util.concurrent.TimeUnit;
 /** The Milvus Client Interface */
 public interface MilvusClient {
 
-    default void close() {
+  default void close() {
     close(TimeUnit.MINUTES.toSeconds(1));
   }
 
-    void close(long maxWaitSeconds);
+  void close(long maxWaitSeconds);
+
+  R<MutationResult> insert(InsertParam insertParam);
+
+  R<FlushResponse> flush(String collectionName,String dbName);
+
+  R<FlushResponse> flush(String collectionName);
+
+  R<FlushResponse> flush(List<String> collectionNames);
+
+  R<FlushResponse> flush(List<String> collectionNames, String dbName);
+
+  R<MutationResult> delete(DeleteParam deleteParam);
+
+  R<SearchResults> search(SearchParam searchParam);
+
+  R<QueryResults> query(QueryParam queryParam);
+
+  R<CalcDistanceResults> calcDistance(CalcDistanceParam calcDistanceParam);
 
     /**
      * Check if a collection exists.

+ 1 - 18
src/main/java/io/milvus/client/MilvusServiceClient.java

@@ -21,10 +21,8 @@ package io.milvus.client;
 
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
-import io.milvus.grpc.MilvusServiceGrpc;
 import io.milvus.param.ConnectParam;
-import io.milvus.param.R;
-import io.milvus.param.collection.HasCollectionParam;
+import io.milvus.grpc.MilvusServiceGrpc;
 
 import java.util.concurrent.TimeUnit;
 
@@ -75,20 +73,5 @@ public class MilvusServiceClient extends AbstractMilvusGrpcClient {
     }
 
 
-
-    public static void main(String[] args) {
-        ConnectParam build = ConnectParam.Builder.newBuilder()
-                .withHost("localhost")
-                .withPort(19530)
-                .build();
-
-        MilvusServiceClient milvusServiceClient = new MilvusServiceClient(build);
-
-        R<Boolean> chuwutest = milvusServiceClient.hasCollection(HasCollectionParam.Builder.newBuilder().withCollectionName("czc1").build());
-
-        System.out.println(chuwutest);
-    }
-
-
 }
 

+ 35 - 0
src/main/java/io/milvus/exception/ParamException.java

@@ -0,0 +1,35 @@
+package io.milvus.exception;
+
+public class ParamException extends RuntimeException{
+    private String msg;
+    private Integer status;
+
+    public ParamException(String msg) {
+        this.msg = msg;
+        this.status = -1;
+    }
+
+
+    public ParamException(String msg, Integer status) {
+        this.msg = msg;
+        this.status = status;
+    }
+
+
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+}

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

@@ -0,0 +1,12 @@
+package io.milvus.param;
+
+public class Constant {
+
+    // default value for search key
+    public static String vectorTag = "$0";
+    public static String vectorFiled = "anns_field";
+    public static String topK = "topk";
+    public static String metricType = "metric_type";
+    public static String parmas = "params";
+
+}

+ 15 - 0
src/main/java/io/milvus/param/MetricType.java

@@ -0,0 +1,15 @@
+package io.milvus.param;
+
+public enum MetricType {
+    INVALID,
+    L2,
+    IP,
+    //Only supported for byte vectors
+    HAMMING,
+    JACCARD,
+    TANIMOTO,
+    SUBSTRUCTURE,
+    SUPERSTRUCTURE,
+    ;
+
+}

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

@@ -1,5 +1,6 @@
 package io.milvus.param;
 
+import io.milvus.grpc.ErrorCode;
 import java.util.Arrays;
 import java.util.Optional;
 
@@ -32,6 +33,7 @@ public class R<T> {
         this.data = data;
     }
 
+;
     public static <T> R<T> failed(Exception exception){
         R<T> r = new R<>();
         r.setStatus(Status.Unknown.getCode());
@@ -39,6 +41,13 @@ public class R<T> {
         return r;
     }
 
+    public static <T> R<T> failed(ErrorCode errorCode) {
+        R<T> r = new R<>();
+        r.setStatus(errorCode.ordinal());
+        r.setException(new Exception(errorCode.name()));
+        return r;
+    }
+
     public static <T> R<T> failed(Status statusCode){
         R<T> r = new R<>();
         r.setStatus(statusCode.getCode());

+ 38 - 0
src/main/java/io/milvus/param/dml/CalcDistanceParam.java

@@ -0,0 +1,38 @@
+package io.milvus.param.dml;
+
+import io.milvus.exception.ParamException;
+import io.milvus.param.MetricType;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+
+/**
+ * only support two vectors cal
+ */
+public class CalcDistanceParam {
+    private final List<Float> vector1;
+    private final List<Float> vector2;
+    private final MetricType metricType;
+
+    public CalcDistanceParam(@Nonnull List<Float> vector1,@Nonnull List<Float> vector2,@Nonnull MetricType metricType){
+        if (vector1.size() != vector2.size()){
+            throw new ParamException("size is not equal");
+        }
+
+        this.vector1 = vector1;
+        this.vector2 = vector2;
+        this.metricType = metricType;
+    }
+
+    public List<Float> getVector1() {
+        return vector1;
+    }
+
+    public List<Float> getVector2() {
+        return vector2;
+    }
+
+    public MetricType getMetricType() {
+        return metricType;
+    }
+}

+ 60 - 0
src/main/java/io/milvus/param/dml/DeleteParam.java

@@ -0,0 +1,60 @@
+package io.milvus.param.dml;
+
+import javax.annotation.Nonnull;
+
+public class DeleteParam {
+    private final String dbName;
+    private final String collectionName;
+    private final String partitionName;
+
+    private DeleteParam(@Nonnull Builder builder) {
+        this.dbName = builder.dbName;
+        this.collectionName = builder.collectionName;
+        this.partitionName = builder.partitionName;
+    }
+
+    public String getDbName() {
+        return dbName;
+    }
+
+    public String getCollectionName() {
+        return collectionName;
+    }
+
+    public String getPartitionName() {
+        return partitionName;
+    }
+
+    public static class Builder {
+        private String dbName = "";
+        private String collectionName;
+        private String partitionName ;
+
+        private Builder() {
+        }
+
+        public static Builder nweBuilder() {
+            return new Builder();
+        }
+
+        public Builder setPartitionName(@Nonnull String partitionName) {
+            this.partitionName = partitionName;
+            return this;
+        }
+
+        public Builder setDbName(@Nonnull String dbName){
+            this.dbName = dbName;
+            return this;
+        }
+
+        public Builder setCollectionName(@Nonnull String collectionName){
+            this.collectionName = collectionName;
+            return this;
+        }
+
+        public DeleteParam build() {
+            return new DeleteParam(this);
+        }
+
+    }
+}

+ 105 - 0
src/main/java/io/milvus/param/dml/InsertParam.java

@@ -0,0 +1,105 @@
+package io.milvus.param.dml;
+
+import io.milvus.grpc.DataType;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+
+/**
+ * fieldNames,dataTypes, fieldValues' order must be consistent.
+ * explain fieldValues:
+ *    if dataType is scalar: ? is basic type, like Integer,Long...
+ *    if dataType is FloatVector: ? is List<Float>
+ */
+public class InsertParam {
+    private final String collectionName;
+    private final String partitionName;
+    //for check collectionFields
+    private final int fieldNum;
+    // field's name
+    private final List<String> fieldNames;
+    // field's dataType
+    private final List<DataType> dataTypes;
+    // field's values
+    private final List<List<?>> fieldValues;
+
+    private InsertParam(@Nonnull Builder builder) {
+        this.collectionName = builder.collectionName;
+        this.partitionName = builder.partitionName;
+        this.fieldNum = builder.fieldNum;
+        this.fieldNames = builder.fieldNames;
+        this.dataTypes = builder.dataTypes;
+        this.fieldValues = builder.fieldValues;
+    }
+
+    public String getCollectionName() {
+        return collectionName;
+    }
+
+    public String getPartitionName() {
+        return partitionName;
+    }
+
+    public int getFieldNum() {
+        return fieldNum;
+    }
+
+    public List<String> getFieldNames() {
+        return fieldNames;
+    }
+
+    public List<DataType> getDataTypes() {
+        return dataTypes;
+    }
+
+    public List<List<?>> getFieldValues() {
+        return fieldValues;
+    }
+
+    public static class Builder {
+        private final String collectionName;
+        private String partitionName = "_default";
+        private int fieldNum;
+        private List<String> fieldNames;
+        private List<DataType> dataTypes;
+        private List<List<?>> fieldValues;
+
+        private Builder(@Nonnull String collectionName) {
+            this.collectionName = collectionName;
+        }
+
+        public static Builder nweBuilder(@Nonnull String collectionName) {
+            return new Builder(collectionName);
+        }
+
+        public Builder setPartitionName(@Nonnull String partitionName) {
+            this.partitionName = partitionName;
+            return this;
+        }
+
+        public Builder setFieldNum(int fieldNum) {
+            this.fieldNum = fieldNum;
+            return this;
+        }
+
+        public Builder setFieldNames(@Nonnull List<String> fieldNames) {
+            this.fieldNames = fieldNames;
+            return this;
+        }
+
+        public Builder setDataTypes(@Nonnull List<DataType> dataTypes) {
+            this.dataTypes = dataTypes;
+            return this;
+        }
+
+        public Builder setFieldValues(@Nonnull List<List<?>> fieldValues) {
+            this.fieldValues = fieldValues;
+            return this;
+        }
+
+        public InsertParam build() {
+            return new InsertParam(this);
+        }
+
+    }
+}

+ 89 - 0
src/main/java/io/milvus/param/dml/QueryParam.java

@@ -0,0 +1,89 @@
+package io.milvus.param.dml;
+
+import com.google.common.collect.Lists;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.List;
+
+public class QueryParam {
+    private final String dbName;
+    private final String collectionName;
+    private final List<String> partitionNames;
+    private final List<String> outFields;
+    private final String expr;
+
+    private QueryParam(@Nonnull Builder builder){
+        this.dbName = builder.dbName;
+        this.collectionName = builder.collectionName;
+        this.partitionNames = builder.partitionNames;
+        this.outFields = builder.outFields;
+        this.expr = builder.expr;
+    }
+
+    public String getDbName() {
+        return dbName;
+    }
+
+    public String getCollectionName() {
+        return collectionName;
+    }
+
+    public List<String> getPartitionNames() {
+        return partitionNames;
+    }
+
+    public List<String> getOutFields() {
+        return outFields;
+    }
+
+    public String getExpr() {
+        return expr;
+    }
+
+    public static class Builder{
+        private String dbName = "";
+        private String collectionName;
+        private List<String> partitionNames = Lists.newArrayList();
+        private List<String> outFields = new ArrayList<>();
+        private String expr;
+
+        private Builder(@Nonnull String expr){
+            this.expr = expr;
+        }
+
+        public static Builder newBuilder(@Nonnull String expr){
+            return new Builder(expr);
+        }
+
+        public Builder setDbName(@Nonnull String dbName){
+            this.dbName = dbName;
+            return this;
+        }
+
+        public Builder setCollectionName(@Nonnull String collectionName){
+            this.collectionName = collectionName;
+            return this;
+        }
+
+        public Builder setPartitionNames(@Nonnull List<String> partitionNames){
+            this.partitionNames = partitionNames;
+            return this;
+        }
+
+        public Builder setOutFields(List<String> outFields) {
+            this.outFields = outFields;
+            return this;
+        }
+
+        public Builder setExpr(String expr) {
+            this.expr = expr;
+            return this;
+        }
+
+        public QueryParam build(){
+            return new QueryParam(this);
+        }
+    }
+
+}

+ 165 - 0
src/main/java/io/milvus/param/dml/SearchParam.java

@@ -0,0 +1,165 @@
+package io.milvus.param.dml;
+
+import com.google.common.collect.Lists;
+import io.milvus.grpc.DslType;
+import io.milvus.param.MetricType;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SearchParam {
+    private final String dbName;
+    private final String collectionName;
+    private final List<String> partitionNames;
+    private final MetricType metricType;
+    private final String vectorFieldName;
+    private final Integer topK;
+    private final DslType dslType;
+    private final String dsl;
+    private final List<String> outFields;
+    private final List<List<Float>> vectors;
+    private final Map<String,String> params;
+
+    private SearchParam(@Nonnull Builder builder){
+        this.dbName = builder.dbName;
+        this.collectionName = builder.collectionName;
+        this.partitionNames = builder.partitionNames;
+        this.metricType = builder.metricType;
+        this.vectorFieldName = builder.vectorFieldName;
+        this.topK = builder.topK;
+        this.dslType = builder.dslType;
+        this.dsl = builder.dsl;
+        this.outFields = builder.outFields;
+        this.vectors = builder.vectors;
+        this.params = builder.params;
+    }
+
+    public String getDbName() {
+        return dbName;
+    }
+
+    public String getCollectionName() {
+        return collectionName;
+    }
+
+    public List<String> getPartitionNames() {
+        return partitionNames;
+    }
+
+    public MetricType getMetricType() {
+        return metricType;
+    }
+
+    public String getVectorFieldName() {
+        return vectorFieldName;
+    }
+
+    public Integer getTopK() {
+        return topK;
+    }
+
+    public DslType getDslType() {
+        return dslType;
+    }
+
+    public String getDsl() {
+        return dsl;
+    }
+
+    public List<String> getOutFields() {
+        return outFields;
+    }
+
+    public List<List<Float>> getVectors() {
+        return vectors;
+    }
+
+    public Map<String, String> getParams() {
+        return params;
+    }
+
+    public static class Builder{
+        private String dbName = "";
+        private String collectionName;
+        private List<String> partitionNames = Lists.newArrayList();
+        private MetricType metricType = MetricType.L2;
+        private String vectorFieldName;
+        private Integer topK;
+        private DslType dslType = DslType.BoolExprV1;
+        private String dsl;
+        private List<String> outFields = new ArrayList<>();
+        private List<List<Float>> vectors;
+        private Map<String,String> params = new HashMap<>();
+
+        private Builder(){
+        }
+
+        public static Builder newBuilder(){
+            return new Builder();
+        }
+
+        public Builder setDbName(@Nonnull String dbName){
+            this.dbName = dbName;
+            return this;
+        }
+
+        public Builder setCollectionName(@Nonnull String collectionName){
+            this.collectionName = collectionName;
+            return this;
+        }
+
+        public Builder setPartitionNames(@Nonnull List<String> partitionNames){
+            this.partitionNames = partitionNames;
+            return this;
+        }
+
+        public Builder setMetricType(@Nonnull MetricType metricType) {
+            this.metricType = metricType;
+            return this;
+        }
+
+        public Builder setVectorFieldName(@Nonnull String vectorFieldName) {
+            this.vectorFieldName = vectorFieldName;
+            return this;
+        }
+
+        public Builder setTopK(@Nonnull Integer topK) {
+            this.topK = topK;
+            return this;
+        }
+
+        public Builder setDslType(@Nonnull DslType dslType) {
+            this.dslType = dslType;
+            return this;
+        }
+
+        public Builder setDsl(@Nonnull String dsl) {
+            this.dsl = dsl;
+            return this;
+        }
+
+        public Builder setOutFields(@Nonnull List<String> outFields) {
+            this.outFields = outFields;
+            return this;
+        }
+
+        public Builder setVectors(@Nonnull List<List<Float>> vectors) {
+            this.vectors = vectors;
+            return this;
+        }
+
+
+        public Builder setParams(@Nonnull Map<String, String> params) {
+            this.params = params;
+            return this;
+        }
+
+        public SearchParam build(){
+            return new SearchParam(this);
+        }
+    }
+
+}

+ 4 - 0
src/test/java/io/milvus/client/MilvusClientTest.java

@@ -0,0 +1,4 @@
+package io.milvus.client;
+
+public class MilvusClientTest {
+}