浏览代码

Simplify `insert`

jianghua 4 年之前
父节点
当前提交
4f5e875025

+ 72 - 104
src/main/java/io/milvus/client/InsertParam.java

@@ -19,125 +19,93 @@
 
 package io.milvus.client;
 
-import java.util.Map;
-import javax.annotation.Nonnull;
-import java.util.ArrayList;
+import com.google.protobuf.ByteString;
+import io.milvus.client.exception.UnsupportedDataType;
+import io.milvus.grpc.AttrRecord;
+import io.milvus.grpc.FieldValue;
+import io.milvus.grpc.VectorRecord;
+import io.milvus.grpc.VectorRowRecord;
+
+import java.nio.ByteBuffer;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /** Contains parameters for <code>insert</code> */
 public class InsertParam {
-  private final String collectionName;
-  private final List<? extends Map<String, Object>> fields;
-  private final List<Long> entityIds;
-  private final String partitionTag;
+  private io.milvus.grpc.InsertParam.Builder builder;
 
-  private InsertParam(@Nonnull Builder builder) {
-    this.collectionName = builder.collectionName;
-    this.fields = builder.fields;
-    this.entityIds = builder.entityIds;
-    this.partitionTag = builder.partitionTag;
+  public static InsertParam create(String collectionName) {
+    return new InsertParam(collectionName);
   }
 
-  public String getCollectionName() {
-    return collectionName;
+  private InsertParam(String collectionName) {
+    this.builder = io.milvus.grpc.InsertParam.newBuilder();
+    builder.setCollectionName(collectionName);
   }
 
-  public List<? extends Map<String, Object>> getFields() { return fields; }
-
-  public List<Long> getEntityIds() {
-    return entityIds;
-  }
-
-  public String getPartitionTag() {
-    return partitionTag;
+  public InsertParam setEntityIds(List<Long> entityIds) {
+    builder.addAllEntityIdArray(entityIds);
+    return this;
   }
 
-  /** Builder for <code>InsertParam</code> */
-  public static class Builder {
-    // Required parameter
-    private final String collectionName;
-
-    // Optional parameters - initialized to default values
-    private List<Map<String, Object>> fields = new ArrayList<>();
-    private List<Long> entityIds = new ArrayList<>();
-    private String partitionTag = "";
-
-    /** @param collectionName collection to insert entities to */
-    public Builder(@Nonnull String collectionName) {
-      this.collectionName = collectionName;
-    }
-
-    /**
-     * The data you wish to insert into collections. Default to an empty <code>ArrayList</code>
-     *
-     * @param fields a <code>List</code> of <code>Map</code> that contains data to insert for each
-     *     field name. "field", "values" and "type" must be present in each map. The size of
-     *     map["values"] must match for all maps in the list, which is equivalent to entity count.
-     *     Example fields:
-     * <pre>
-     *     <code>
-     *   [
-     *         {"field": "A", "values": A_list, "type": DataType.INT32},
-     *         {"field": "B", "values": B_list, "type": DataType.INT32},
-     *         {"field": "C", "values": C_list, "type": DataType.INT64},
-     *         {"field": "Vec", "values": vecs, "type": DataType.VECTOR_FLOAT}
-     *   ]
-     *     </code>
-     * </pre>
-     *
-     * @return <code>Builder</code>
-     */
-    public Builder withFields(@Nonnull List<Map<String, Object>> fields) {
-      this.fields = fields;
-      return this;
-    }
-
-    /**
-     * Add a single field to collection. Example field:
-     * <pre>
-     *   <code>
-     *      {"field": "A", "values": A_list, "type": DataType.INT64}, or
-     *      {"field": "B", "values": B_list, "type": DataType.INT32}, or
-     *      {"field": "C", "values": C_list, "type": DataType.FLOAT}, or
-     *      {"field": "Vec", "values": vecs, "type": DataType.VECTOR_FLOAT}
-     *   </code>
-     * </pre>
-     *
-     * @param field A field must have keys "field", "values" and "type".
-     *              <code>FieldBuilder</code> can be used to create a field.
-     * @see FieldBuilder
-     * @return <code>Builder</code>
-     */
-    public Builder field(@Nonnull Map<String, Object> field) {
-      this.fields.add(field);
-      return this;
+  public <T> InsertParam addField(String name, DataType type, List<T> values) {
+    AttrRecord.Builder record = AttrRecord.newBuilder();
+    switch (type) {
+      case INT32:
+        record.addAllInt32Value((List<Integer>) values);
+        break;
+      case INT64:
+        record.addAllInt64Value((List<Long>) values);
+        break;
+      case FLOAT:
+        record.addAllFloatValue((List<Float>) values);
+        break;
+      case DOUBLE:
+        record.addAllDoubleValue((List<Double>) values);
+        break;
+      default:
+        throw new UnsupportedDataType("Unsupported data type: " + type.name());
     }
+    builder.addFields(FieldValue.newBuilder()
+        .setFieldName(name)
+        .setTypeValue(type.getVal())
+        .setAttrRecord(record.build())
+        .build());
+    return this;
+  }
 
-    /**
-     * Optional. Default to an empty <code>ArrayList</code>. Only needed when entity ids are not
-     * auto-generated by milvus. This is specified when creating collection.
-     *
-     * @param entityIds a <code>List</code> of ids associated with the entities to insert.
-     * @return <code>Builder</code>
-     */
-    public Builder withEntityIds(@Nonnull List<Long> entityIds) {
-      this.entityIds = entityIds;
-      return this;
+  public <T> InsertParam addVectorField(String name, DataType type, List<T> values) {
+    VectorRecord.Builder record = VectorRecord.newBuilder();
+    switch (type) {
+      case VECTOR_FLOAT:
+        record.addAllRecords(
+            ((List<List<Float>>) values).stream()
+                .map(row -> VectorRowRecord.newBuilder().addAllFloatData(row).build())
+                .collect(Collectors.toList()));
+        break;
+      case VECTOR_BINARY:
+        record.addAllRecords(
+            ((List<ByteBuffer>) values).stream()
+                .map(row -> VectorRowRecord.newBuilder().setBinaryData(ByteString.copyFrom(row.slice())).build())
+                .collect(Collectors.toList()));
+        break;
+      default:
+        throw new UnsupportedDataType("Unsupported data type: " + type.name());
     }
+    builder.addFields(FieldValue.newBuilder()
+        .setFieldName(name)
+        .setTypeValue(type.getVal())
+        .setVectorRecord(record.build())
+        .build());
+    return this;
+  }
 
-    /**
-     * Optional. Default to an empty <code>String</code>
-     *
-     * @param partitionTag partition tag
-     * @return <code>Builder</code>
-     */
-    public Builder withPartitionTag(@Nonnull String partitionTag) {
-      this.partitionTag = partitionTag;
-      return this;
-    }
+  public InsertParam setPartitionTag(String partitionTag) {
+    builder.setPartitionTag(partitionTag);
+    return this;
+  }
 
-    public InsertParam build() {
-      return new InsertParam(this);
-    }
+  io.milvus.grpc.InsertParam grpc() {
+    return builder.build();
   }
 }

+ 4 - 8
src/main/java/io/milvus/client/MilvusClient.java

@@ -194,12 +194,10 @@ public interface MilvusClient {
    * </code>
    * </pre>
    *
-   * @return <code>InsertResponse</code>
+   * @return a list of ids for the inserted entities
    * @see InsertParam
-   * @see InsertResponse
-   * @see Response
    */
-  InsertResponse insert(InsertParam insertParam);
+  List<Long> insert(InsertParam insertParam);
 
   /**
    * Inserts data specified by <code>insertParam</code> asynchronously
@@ -216,13 +214,11 @@ public interface MilvusClient {
    * </code>
    * </pre>
    *
-   * @return a <code>ListenableFuture</code> object which holds the <code>InsertResponse</code>
+   * @return a <code>ListenableFuture</code> object which holds the list of ids for the inserted entities.
    * @see InsertParam
-   * @see InsertResponse
-   * @see Response
    * @see ListenableFuture
    */
-  ListenableFuture<InsertResponse> insertAsync(InsertParam insertParam);
+  ListenableFuture<List<Long>> insertAsync(InsertParam insertParam);
 
   /**
    * Searches entities specified by <code>searchParam</code>

+ 11 - 242
src/main/java/io/milvus/client/MilvusGrpcClient.java

@@ -326,252 +326,21 @@ abstract class AbstractMilvusGrpcClient implements MilvusClient {
 
   @Override
   @SuppressWarnings("unchecked")
-  public InsertResponse insert(@Nonnull InsertParam insertParam) {
-
-    if (!maybeAvailable()) {
-      logWarning("You are not connected to Milvus server");
-      return new InsertResponse(
-          new Response(Response.Status.CLIENT_NOT_CONNECTED), Collections.emptyList());
-    }
-
-    List<FieldValue> fieldValueList = new ArrayList<>();
-    List<? extends Map<String, Object>> fields = insertParam.getFields();
-    for (Map<String, Object> map : fields) {
-      // process each field
-      if (!map.containsKey("field") || !map.containsKey("type") ||
-          !map.containsKey("values")) {
-        logError("insertParam fields map must contain 'field', 'type' and 'values' keys.");
-        return new InsertResponse(
-            new Response(Response.Status.ILLEGAL_ARGUMENT), Collections.emptyList());
-      }
-      DataType dataType = (DataType) map.get("type");
-      AttrRecord.Builder attrBuilder = AttrRecord.newBuilder();
-      VectorRecord.Builder vectorBuilder = VectorRecord.newBuilder();
-      try {
-        if (dataType == DataType.INT32) {
-          attrBuilder.addAllInt32Value((List<Integer>) map.get("values"));
-        } else if (dataType == DataType.INT64) {
-          attrBuilder.addAllInt64Value((List<Long>) map.get("values"));
-        } else if (dataType == DataType.FLOAT) {
-          attrBuilder.addAllFloatValue((List<Float>) map.get("values"));
-        } else if (dataType == DataType.DOUBLE) {
-          attrBuilder.addAllDoubleValue((List<Double>) map.get("values"));
-        } else if (dataType == DataType.VECTOR_FLOAT) {
-          List<List<Float>> floatVectors = (List<List<Float>>) map.get("values");
-          List<VectorRowRecord> vectorRowRecordList = new ArrayList<>();
-          for (List<Float> floatVector : floatVectors) {
-            vectorRowRecordList.add(
-                VectorRowRecord.newBuilder()
-                    .addAllFloatData(floatVector)
-                    .build());
-          }
-          vectorBuilder.addAllRecords(vectorRowRecordList);
-        } else if (dataType == DataType.VECTOR_BINARY) {
-          List<List<Byte>> binaryVectors = (List<List<Byte>>) map.get("values");
-          List<VectorRowRecord> vectorRowRecordList = new ArrayList<>();
-          for (List<Byte> binaryVector : binaryVectors) {
-            ByteBuffer byteBuffer = ByteBuffer.allocate(binaryVector.size());
-            for (int i = 0; i < binaryVector.size(); i++) {
-              byteBuffer = byteBuffer.put(i, binaryVector.get(i));
-            }
-            vectorRowRecordList.add(
-                VectorRowRecord.newBuilder()
-                    .setBinaryData(ByteString.copyFrom(byteBuffer))
-                    .build());
-          }
-          vectorBuilder.addAllRecords(vectorRowRecordList);
-        } else {
-          logError("insertParam `values` DataType unsupported.");
-          return new InsertResponse(
-              new Response(Response.Status.ILLEGAL_ARGUMENT), Collections.emptyList());
-        }
-      } catch (Exception e) {
-        logError("insertParam `values` invalid.");
-        return new InsertResponse(
-            new Response(Response.Status.ILLEGAL_ARGUMENT), Collections.emptyList());
-      }
-
-      AttrRecord attrRecord = attrBuilder.build();
-      VectorRecord vectorRecord = vectorBuilder.build();
-
-      FieldValue fieldValue =
-          FieldValue.newBuilder()
-              .setFieldName(map.get("field").toString())
-              .setTypeValue(((DataType) map.get("type")).getVal())
-              .setAttrRecord(attrRecord)
-              .setVectorRecord(vectorRecord)
-              .build();
-      fieldValueList.add(fieldValue);
-    }
-
-    io.milvus.grpc.InsertParam request =
-        io.milvus.grpc.InsertParam.newBuilder()
-            .setCollectionName(insertParam.getCollectionName())
-            .addAllFields(fieldValueList)
-            .addAllEntityIdArray(insertParam.getEntityIds())
-            .setPartitionTag(insertParam.getPartitionTag())
-            .build();
-
-    EntityIds response;
-
-    try {
-      response = blockingStub().insert(request);
-
-      if (response.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
-        logInfo(
-            "Inserted {} vectors to collection `{}` successfully!",
-            response.getEntityIdArrayCount(),
-            insertParam.getCollectionName());
-        return new InsertResponse(
-            new Response(Response.Status.SUCCESS), response.getEntityIdArrayList());
-      } else {
-        logError("Insert vectors failed:\n{}", response.getStatus().toString());
-        return new InsertResponse(
-            new Response(
-                Response.Status.valueOf(response.getStatus().getErrorCodeValue()),
-                response.getStatus().getReason()),
-            Collections.emptyList());
-      }
-    } catch (StatusRuntimeException e) {
-      logError("insert RPC failed:\n{}", e.getStatus().toString());
-      return new InsertResponse(
-          new Response(Response.Status.RPC_ERROR, e.toString()), Collections.emptyList());
-    }
+  public List<Long> insert(@Nonnull InsertParam insertParam) {
+    return translateExceptions(() -> Futures.getUnchecked(insertAsync(insertParam)));
   }
 
   @Override
   @SuppressWarnings("unchecked")
-  public ListenableFuture<InsertResponse> insertAsync(@Nonnull InsertParam insertParam) {
-
-    if (!maybeAvailable()) {
-      logWarning("You are not connected to Milvus server");
-      return Futures.immediateFuture(
-          new InsertResponse(
-              new Response(Response.Status.CLIENT_NOT_CONNECTED), Collections.emptyList()));
-    }
-
-    List<FieldValue> fieldValueList = new ArrayList<>();
-    List<? extends Map<String, Object>> fields = insertParam.getFields();
-    for (Map<String, Object> map : fields) {
-      // process each field
-      if (!map.containsKey("field") || !map.containsKey("type") ||
-          !map.containsKey("values")) {
-        logError("insertParam fields map must contain 'field', 'type' and 'values' keys.");
-        return Futures.immediateFuture(
-            new InsertResponse(
-                new Response(Response.Status.ILLEGAL_ARGUMENT), Collections.emptyList()));
-      }
-      DataType dataType = (DataType) map.get("type");
-      AttrRecord.Builder attrBuilder = AttrRecord.newBuilder();
-      VectorRecord.Builder vectorBuilder = VectorRecord.newBuilder();
-      try {
-        if (dataType == DataType.INT32) {
-          attrBuilder.addAllInt32Value((List<Integer>) map.get("values"));
-        } else if (dataType == DataType.INT64) {
-          attrBuilder.addAllInt64Value((List<Long>) map.get("values"));
-        } else if (dataType == DataType.FLOAT) {
-          attrBuilder.addAllFloatValue((List<Float>) map.get("values"));
-        } else if (dataType == DataType.DOUBLE) {
-          attrBuilder.addAllDoubleValue((List<Double>) map.get("values"));
-        } else if (dataType == DataType.VECTOR_FLOAT) {
-          List<List<Float>> floatVectors = (List<List<Float>>) map.get("values");
-          List<VectorRowRecord> vectorRowRecordList = new ArrayList<>();
-          for (List<Float> floatVector : floatVectors) {
-            vectorRowRecordList.add(
-                VectorRowRecord.newBuilder()
-                    .addAllFloatData(floatVector)
-                    .build());
-          }
-          vectorBuilder.addAllRecords(vectorRowRecordList);
-        } else if (dataType == DataType.VECTOR_BINARY) {
-          List<List<Byte>> binaryVectors = (List<List<Byte>>) map.get("values");
-          List<VectorRowRecord> vectorRowRecordList = new ArrayList<>();
-          for (List<Byte> binaryVector : binaryVectors) {
-            ByteBuffer byteBuffer = ByteBuffer.allocate(binaryVector.size());
-            for (int i = 0; i < binaryVector.size(); i++) {
-              byteBuffer = byteBuffer.put(i, binaryVector.get(i));
-            }
-            vectorRowRecordList.add(
-                VectorRowRecord.newBuilder()
-                    .setBinaryData(ByteString.copyFrom(byteBuffer))
-                    .build());
-          }
-          vectorBuilder.addAllRecords(vectorRowRecordList);
-        } else {
-          logError("insertParam `values` DataType unsupported.");
-          return Futures.immediateFuture(
-              new InsertResponse(
-                  new Response(Response.Status.ILLEGAL_ARGUMENT), Collections.emptyList()));
-        }
-      } catch (Exception e) {
-        logError("insertParam `values` invalid.");
-        return Futures.immediateFuture(
-            new InsertResponse(
-                new Response(Response.Status.ILLEGAL_ARGUMENT), Collections.emptyList()));
-      }
-
-      AttrRecord attrRecord = attrBuilder.build();
-      VectorRecord vectorRecord = vectorBuilder.build();
-
-      FieldValue fieldValue =
-          FieldValue.newBuilder()
-              .setFieldName(map.get("field").toString())
-              .setTypeValue(((DataType) map.get("type")).getVal())
-              .setAttrRecord(attrRecord)
-              .setVectorRecord(vectorRecord)
-              .build();
-      fieldValueList.add(fieldValue);
-    }
-
-    io.milvus.grpc.InsertParam request =
-        io.milvus.grpc.InsertParam.newBuilder()
-            .setCollectionName(insertParam.getCollectionName())
-            .addAllFields(fieldValueList)
-            .addAllEntityIdArray(insertParam.getEntityIds())
-            .setPartitionTag(insertParam.getPartitionTag())
-            .build();
-
-    ListenableFuture<EntityIds> response;
-
-    response = futureStub().insert(request);
-
-    Futures.addCallback(
-        response,
-        new FutureCallback<EntityIds>() {
-          @Override
-          public void onSuccess(EntityIds result) {
-            if (result.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
-              logInfo(
-                  "Inserted {} vectors to collection `{}` successfully!",
-                  result.getEntityIdArrayCount(),
-                  insertParam.getCollectionName());
-            } else {
-              logError("InsertAsync failed:\n{}", result.getStatus().toString());
-            }
-          }
-
-          @Override
-          public void onFailure(Throwable t) {
-            logError("InsertAsync failed:\n{}", t.getMessage());
-          }
-        },
-        MoreExecutors.directExecutor());
-
-    Function<EntityIds, InsertResponse> transformFunc =
-        vectorIds -> {
-          if (vectorIds.getStatus().getErrorCode() == ErrorCode.SUCCESS) {
-            return new InsertResponse(
-                new Response(Response.Status.SUCCESS), vectorIds.getEntityIdArrayList());
-          } else {
-            return new InsertResponse(
-                new Response(
-                    Response.Status.valueOf(vectorIds.getStatus().getErrorCodeValue()),
-                    vectorIds.getStatus().getReason()),
-                Collections.emptyList());
-          }
-        };
-
-    return Futures.transform(response, transformFunc::apply, MoreExecutors.directExecutor());
+  public ListenableFuture<List<Long>> insertAsync(@Nonnull InsertParam insertParam) {
+    return translateExceptions(() -> {
+      io.milvus.grpc.InsertParam request = insertParam.grpc();
+      ListenableFuture<EntityIds> responseFuture = futureStub().insert(request);
+      return Futures.transform(responseFuture, entityIds -> {
+        checkResponseStatus(entityIds.getStatus());
+        return entityIds.getEntityIdArrayList();
+      }, MoreExecutors.directExecutor());
+    });
   }
 
   @Override

+ 7 - 0
src/main/java/io/milvus/client/exception/UnsupportedDataType.java

@@ -0,0 +1,7 @@
+package io.milvus.client.exception;
+
+public class UnsupportedDataType extends ClientSideMilvusException {
+  public UnsupportedDataType(String message) {
+    super(null, message);
+  }
+}

+ 104 - 240
src/test/java/io/milvus/client/MilvusGrpcClientTest.java

@@ -20,15 +20,11 @@
 package io.milvus.client;
 
 import com.google.common.collect.ImmutableMap;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
 import io.grpc.NameResolverProvider;
 import io.grpc.NameResolverRegistry;
 import io.grpc.Status;
 import io.grpc.StatusRuntimeException;
-import io.milvus.client.InsertParam.Builder;
 import io.milvus.client.exception.ClientSideMilvusException;
 import io.milvus.client.exception.InitializationException;
 import io.milvus.client.exception.ServerSideMilvusException;
@@ -36,7 +32,6 @@ import io.milvus.client.exception.UnsupportedServerVersion;
 import io.milvus.grpc.ErrorCode;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.text.RandomStringGenerator;
-import org.checkerframework.checker.nullness.compatqual.NullableDecl;
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
@@ -153,16 +148,14 @@ class MilvusClientTest {
   }
 
   // Helper function that generates random binary vectors
-  static List<List<Byte>> generateBinaryVectors(int vectorCount, int dimension) {
+  static List<ByteBuffer> generateBinaryVectors(int vectorCount, int dimension) {
     Random random = new Random();
-    List<List<Byte>> vectors = new ArrayList<>(vectorCount);
+    List<ByteBuffer> vectors = new ArrayList<>(vectorCount);
     final int dimensionInByte = dimension / 8;
     for (int i = 0; i < vectorCount; ++i) {
       ByteBuffer byteBuffer = ByteBuffer.allocate(dimensionInByte);
       random.nextBytes(byteBuffer.array());
-      byte[] b = new byte[byteBuffer.remaining()];
-      byteBuffer.get(b);
-      vectors.add(Arrays.asList(ArrayUtils.toObject(b)));
+      vectors.add(byteBuffer);
     }
     return vectors;
   }
@@ -371,40 +364,26 @@ class MilvusClientTest {
       intValues.add((long) i);
       floatValues.add((float) i);
     }
+
     List<Long> entityIds1 = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(entityIds1)
-            .withPartitionTag(tag1)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(entityIds1)
+        .setPartitionTag(tag1);
+    client.insert(insertParam);
+
     List<Long> entityIds2 = LongStream.range(size, size * 2).boxed().collect(Collectors.toList());
-    insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(entityIds2)
-            .withPartitionTag(tag2)
-            .build();
-    insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
+    insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(entityIds2)
+        .setPartitionTag(tag2);
+    client.insert(insertParam);
 
     assertTrue(client.flush(randomCollectionName).ok());
 
@@ -479,65 +458,16 @@ class MilvusClientTest {
       intValues.add((long) i);
       floatValues.add((float) i);
     }
-    List<Long> entityIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(entityIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    assertEquals(size, insertResponse.getEntityIds().size());
-  }
 
-  @org.junit.jupiter.api.Test
-  void insertAsync() throws ExecutionException, InterruptedException {
-    List<Long> intValues = new ArrayList<>(size);
-    List<Float> floatValues = new ArrayList<>(size);
-    List<List<Float>> vectors = generateFloatVectors(size, dimension);
-    for (int i = 0; i < size; i++) {
-      intValues.add((long) i);
-      floatValues.add((float) i);
-    }
     List<Long> entityIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(entityIds)
-            .build();
-    ListenableFuture<InsertResponse> insertResponseFuture = client.insertAsync(insertParam);
-    Futures.addCallback(
-        insertResponseFuture,
-        new FutureCallback<InsertResponse>() {
-          @Override
-          public void onSuccess(@NullableDecl InsertResponse insertResponse) {
-            assert insertResponse != null;
-            assertTrue(insertResponse.ok());
-            assertEquals(size, insertResponse.getEntityIds().size());
-          }
-
-          @Override
-          public void onFailure(Throwable t) {
-            System.out.println(t.getMessage());
-          }
-        }, MoreExecutors.directExecutor()
-    );
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(entityIds);
+
+    assertEquals(entityIds, client.insert(insertParam));
   }
 
   @org.junit.jupiter.api.Test
@@ -552,16 +482,11 @@ class MilvusClientTest {
 
     client.createCollection(collectionMapping);
 
-    List<List<Byte>> vectors = generateBinaryVectors(size, binaryDimension);
-    InsertParam insertParam =
-        new Builder(binaryCollectionName)
-            .field(new FieldBuilder("binary_vec", DataType.VECTOR_BINARY)
-                .values(vectors)
-                .build())
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    assertEquals(size, insertResponse.getEntityIds().size());
+    List<ByteBuffer> vectors = generateBinaryVectors(size, binaryDimension);
+    InsertParam insertParam = InsertParam
+        .create(binaryCollectionName)
+        .addVectorField("binary_vec", DataType.VECTOR_BINARY, vectors);
+    assertEquals(size, client.insert(insertParam).size());
 
     Index index = Index.create(binaryCollectionName, "binary_vec")
         .setIndexType(IndexType.BIN_IVF_FLAT)
@@ -589,22 +514,13 @@ class MilvusClientTest {
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
 
     List<Long> insertIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(insertIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    List<Long> entityIds = insertResponse.getEntityIds();
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(insertIds);
+    List<Long> entityIds = client.insert(insertParam);
     assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(randomCollectionName).ok());
@@ -650,22 +566,13 @@ class MilvusClientTest {
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
 
     List<Long> insertIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(insertIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    List<Long> entityIds = insertResponse.getEntityIds();
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(insertIds);
+    List<Long> entityIds = client.insert(insertParam);
     assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(randomCollectionName).ok());
@@ -720,29 +627,22 @@ class MilvusClientTest {
       intValues.add((long) i);
       floatValues.add((float) i);
     }
-    List<List<Byte>> vectors = generateBinaryVectors(size, binaryDimension);
-
-    InsertParam insertParam =
-        new Builder(binaryCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("binary_vec", DataType.VECTOR_BINARY)
-                .values(vectors)
-                .build())
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    List<Long> entityIds = insertResponse.getEntityIds();
+    List<ByteBuffer> vectors = generateBinaryVectors(size, binaryDimension);
+
+    InsertParam insertParam = InsertParam
+        .create(binaryCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("binary_vec", DataType.VECTOR_BINARY, vectors);
+    List<Long> entityIds = client.insert(insertParam);
     assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(binaryCollectionName).ok());
 
     final int searchSize = 5;
-    List<List<Byte>> vectorsToSearch = vectors.subList(0, searchSize);
+    List<String> vectorsToSearch = vectors.subList(0, searchSize)
+        .stream().map(byteBuffer -> Arrays.toString(byteBuffer.array()))
+        .collect(Collectors.toList());
 
     final long topK = 10;
     SearchParam searchParam =
@@ -862,22 +762,13 @@ class MilvusClientTest {
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
 
     List<Long> insertIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(insertIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    List<Long> entityIds = insertResponse.getEntityIds();
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(insertIds);
+    List<Long> entityIds = client.insert(insertParam);
     assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(randomCollectionName).ok());
@@ -906,18 +797,13 @@ class MilvusClientTest {
 
     client.createCollection(collectionMapping);
 
-    List<List<Byte>> vectors = generateBinaryVectors(size, binaryDimension);
+    List<ByteBuffer> vectors = generateBinaryVectors(size, binaryDimension);
     List<Long> entityIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(binaryCollectionName)
-            .field(new FieldBuilder("binary_vec", DataType.VECTOR_BINARY)
-                .values(vectors)
-                .build())
-            .withEntityIds(entityIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    assertEquals(size, insertResponse.getEntityIds().size());
+    InsertParam insertParam = InsertParam
+        .create(binaryCollectionName)
+        .addVectorField("binary_vec", DataType.VECTOR_BINARY, vectors)
+        .setEntityIds(entityIds);
+    assertEquals(size, client.insert(insertParam).size());
 
     assertTrue(client.flush(binaryCollectionName).ok());
 
@@ -928,8 +814,11 @@ class MilvusClientTest {
     List<Map<String, Object>> fieldsMap = getEntityByIDResponse.getFieldsMap();
     assertTrue(fieldsMap.get(0).get("binary_vec") instanceof List);
     List<Byte> first = (List<Byte>) (fieldsMap.get(0).get("binary_vec"));
-
-    assertArrayEquals(first.toArray(), vectors.get(0).toArray());
+    byte[] bytes = new byte[first.size()];
+    for (int i = 0; i < first.size(); i++) {
+      bytes[i] = first.get(i);
+    }
+    assertEquals(ByteBuffer.wrap(bytes), vectors.get(0));
   }
 
   @org.junit.jupiter.api.Test
@@ -967,27 +856,18 @@ class MilvusClientTest {
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
 
     List<Long> insertIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(insertIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    assertEquals(size, insertResponse.getEntityIds().size());
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(insertIds);
+    List<Long> entityIds = client.insert(insertParam);
+    assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(randomCollectionName).ok());
 
-    assertTrue(client.deleteEntityByID(randomCollectionName,
-        insertResponse.getEntityIds().subList(0, 100)).ok());
+    assertTrue(client.deleteEntityByID(randomCollectionName, entityIds.subList(0, 100)).ok());
     assertTrue(client.flush(randomCollectionName).ok());
     assertEquals(client.countEntities(randomCollectionName).getCollectionEntityCount(), size - 100);
   }
@@ -1014,22 +894,14 @@ class MilvusClientTest {
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
 
     List<Long> insertIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(insertIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    assertEquals(size, insertResponse.getEntityIds().size());
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(insertIds);
+    List<Long> entityIds = client.insert(insertParam);
+    assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(randomCollectionName).ok());
 
@@ -1045,7 +917,7 @@ class MilvusClientTest {
 
     assertTrue(
         client.deleteEntityByID(randomCollectionName,
-            insertResponse.getEntityIds().subList(0, size / 2)).ok());
+            entityIds.subList(0, size / 2)).ok());
     assertTrue(client.flush(randomCollectionName).ok());
     assertTrue(client.compact(
         new CompactParam.Builder(randomCollectionName).withThreshold(0.2).build()).ok());
@@ -1074,22 +946,14 @@ class MilvusClientTest {
     vectors = vectors.stream().map(MilvusClientTest::normalizeVector).collect(Collectors.toList());
 
     List<Long> insertIds = LongStream.range(0, size).boxed().collect(Collectors.toList());
-    InsertParam insertParam =
-        new Builder(randomCollectionName)
-            .field(new FieldBuilder("int64", DataType.INT64)
-                .values(intValues)
-                .build())
-            .field(new FieldBuilder("float", DataType.FLOAT)
-                .values(floatValues)
-                .build())
-            .field(new FieldBuilder("float_vec", DataType.VECTOR_FLOAT)
-                .values(vectors)
-                .build())
-            .withEntityIds(insertIds)
-            .build();
-    InsertResponse insertResponse = client.insert(insertParam);
-    assertTrue(insertResponse.ok());
-    assertEquals(size, insertResponse.getEntityIds().size());
+    InsertParam insertParam = InsertParam
+        .create(randomCollectionName)
+        .addField("int64", DataType.INT64, intValues)
+        .addField("float", DataType.FLOAT, floatValues)
+        .addVectorField("float_vec", DataType.VECTOR_FLOAT, vectors)
+        .setEntityIds(insertIds);
+    List<Long> entityIds = client.insert(insertParam);
+    assertEquals(size, entityIds.size());
 
     assertTrue(client.flush(randomCollectionName).ok());
 
@@ -1108,7 +972,7 @@ class MilvusClientTest {
 
     assertTrue(
         client.deleteEntityByID(randomCollectionName,
-            insertResponse.getEntityIds().subList(0, size / 2)).ok());
+            entityIds.subList(0, size / 2)).ok());
     assertTrue(client.flush(randomCollectionName).ok());
     assertTrue(client.compactAsync(
         new CompactParam.Builder(randomCollectionName).withThreshold(0.8).build()).get().ok());