فهرست منبع

Add examples (#1199)

Signed-off-by: yhmo <yihua.mo@zilliz.com>
groot 5 ماه پیش
والد
کامیت
f41b2ef76e

+ 180 - 0
examples/main/java/io/milvus/v1/ArrayFieldExample.java

@@ -0,0 +1,180 @@
+package io.milvus.v1;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import io.milvus.client.MilvusClient;
+import io.milvus.client.MilvusServiceClient;
+import io.milvus.common.clientenum.ConsistencyLevelEnum;
+import io.milvus.common.utils.JsonUtils;
+import io.milvus.grpc.DataType;
+import io.milvus.grpc.QueryResults;
+import io.milvus.param.*;
+import io.milvus.param.collection.*;
+import io.milvus.param.dml.InsertParam;
+import io.milvus.param.dml.QueryParam;
+import io.milvus.param.index.CreateIndexParam;
+import io.milvus.response.QueryResultsWrapper;
+
+import java.util.*;
+
+public class ArrayFieldExample {
+    private static final String COLLECTION_NAME = "java_sdk_example_array_v1";
+    private static final String ID_FIELD = "id";
+    private static final String VECTOR_FIELD = "vector";
+    private static final Integer VECTOR_DIM = 128;
+
+    private static void queryWithExpr(MilvusClient client, String expr) {
+        R<QueryResults> queryRet = client.query(QueryParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withExpr(expr)
+                .addOutField("array_int32")
+                .addOutField("array_varchar")
+                .build());
+        QueryResultsWrapper queryWrapper = new QueryResultsWrapper(queryRet.getData());
+        System.out.println("\nQuery with expression: " + expr);
+        List<QueryResultsWrapper.RowRecord> records = queryWrapper.getRowRecords();
+        for (QueryResultsWrapper.RowRecord record : records) {
+            System.out.println(record);
+        }
+        System.out.printf("%d items matched%n", records.size());
+        System.out.println("=============================================================");
+    }
+
+    public static void main(String[] args) {
+        // Connect to Milvus server. Replace the "localhost" and port with your Milvus server address.
+        MilvusServiceClient client = new MilvusServiceClient(ConnectParam.newBuilder()
+                .withHost("localhost")
+                .withPort(19530)
+                .build());
+
+        // Define fields
+        List<FieldType> fieldsSchema = Arrays.asList(
+                FieldType.newBuilder()
+                        .withName(ID_FIELD)
+                        .withDataType(DataType.Int64)
+                        .withPrimaryKey(true)
+                        .withAutoID(true)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName(VECTOR_FIELD)
+                        .withDataType(DataType.FloatVector)
+                        .withDimension(VECTOR_DIM)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName("array_int32")
+                        .withDataType(DataType.Array)
+                        .withElementType(DataType.Int32)
+                        .withMaxCapacity(10)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName("array_varchar")
+                        .withDataType(DataType.Array)
+                        .withElementType(DataType.VarChar)
+                        .withMaxCapacity(10)
+                        .withMaxLength(100)
+                        .build()
+        );
+
+        CollectionSchemaParam collectionSchemaParam = CollectionSchemaParam.newBuilder()
+                .withEnableDynamicField(false)
+                .withFieldTypes(fieldsSchema)
+                .build();
+
+        // Drop the collection if exists
+        client.dropCollection(DropCollectionParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+
+        // Create the collection
+        R<RpcStatus> ret = client.createCollection(CreateCollectionParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withSchema(collectionSchemaParam)
+                .build());
+        if (ret.getStatus() != R.Status.Success.getCode()) {
+            throw new RuntimeException("Failed to create collection! Error: " + ret.getMessage());
+        }
+
+        // Specify an index type on the vector field.
+        ret = client.createIndex(CreateIndexParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldName(VECTOR_FIELD)
+                .withIndexType(IndexType.FLAT)
+                .withMetricType(MetricType.L2)
+                .build());
+        if (ret.getStatus() != R.Status.Success.getCode()) {
+            throw new RuntimeException("Failed to create index on vector field! Error: " + ret.getMessage());
+        }
+
+        // Call loadCollection() to enable automatically loading data into memory for searching
+        client.loadCollection(LoadCollectionParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+
+        System.out.println("Collection created");
+
+        // Insert data by column-based
+        Random random = new Random();
+        int rowCount = 100;
+        List<List<Integer>> intArrArray = new ArrayList<>();
+        List<List<String>> strArrArray = new ArrayList<>();
+        for (int i = 0; i < rowCount; i++) {
+            List<Integer> intArray = new ArrayList<>();
+            List<String> strArray = new ArrayList<>();
+            int capacity = random.nextInt(5) + 5;
+            for (int k = 0; k < capacity; k++) {
+                intArray.add((i+k)%100);
+                strArray.add(String.format("string-%d-%d", i, k));
+            }
+            intArrArray.add(intArray);
+            strArrArray.add(strArray);
+        }
+        List<List<Float>> vectors = CommonUtils.generateFloatVectors(VECTOR_DIM, rowCount);
+
+        List<InsertParam.Field> fieldsInsert = new ArrayList<>();
+        fieldsInsert.add(new InsertParam.Field(VECTOR_FIELD, vectors));
+        fieldsInsert.add(new InsertParam.Field("array_int32", intArrArray));
+        fieldsInsert.add(new InsertParam.Field("array_varchar", strArrArray));
+
+        InsertParam insertColumnsParam = InsertParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFields(fieldsInsert)
+                .build();
+
+        client.insert(insertColumnsParam);
+        System.out.println(rowCount + " rows inserted");
+
+        // Insert rows
+        Gson gson = new Gson();
+        List<JsonObject> rows = new ArrayList<>();
+        for (int i = 0; i < rowCount; i++) {
+            JsonObject row = new JsonObject();
+            row.add(VECTOR_FIELD, gson.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
+            row.add("array_int32", JsonUtils.toJsonTree(intArrArray.get(i)));
+            row.add("array_varchar", JsonUtils.toJsonTree(strArrArray.get(i)));
+            rows.add(row);
+        }
+        client.insert(InsertParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withRows(rows)
+                .build());
+        System.out.println(rowCount + " rows inserted");
+
+        // Get row count
+        R<QueryResults> queryRet = client.query(QueryParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withExpr("")
+                .addOutField("count(*)")
+                .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
+                .build());
+        QueryResultsWrapper queryWrapper = new QueryResultsWrapper(queryRet.getData());
+        System.out.printf("%d rows in collection\n", (long)queryWrapper.getFieldWrapper("count(*)").getFieldData().get(0));
+
+        // Query by filtering expression
+        queryWithExpr(client, "array_int32[0] == 99");
+        queryWithExpr(client, "array_int32[1] in [5, 10, 15]");
+        queryWithExpr(client, "array_varchar[0] like \"string-55%\"");
+        queryWithExpr(client, "array_contains(array_varchar, \"string-4-1\")");
+        queryWithExpr(client, "array_contains_any(array_int32, [3, 9])");
+        queryWithExpr(client, "array_contains_all(array_int32, [3, 9])");
+    }
+}

+ 178 - 0
examples/main/java/io/milvus/v1/NullAndDefaultExample.java

@@ -0,0 +1,178 @@
+package io.milvus.v1;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import io.milvus.client.MilvusClient;
+import io.milvus.client.MilvusServiceClient;
+import io.milvus.common.clientenum.ConsistencyLevelEnum;
+import io.milvus.grpc.DataType;
+import io.milvus.grpc.MutationResult;
+import io.milvus.grpc.QueryResults;
+import io.milvus.param.*;
+import io.milvus.param.collection.CreateCollectionParam;
+import io.milvus.param.collection.DropCollectionParam;
+import io.milvus.param.collection.FieldType;
+import io.milvus.param.collection.LoadCollectionParam;
+import io.milvus.param.dml.InsertParam;
+import io.milvus.param.dml.QueryParam;
+import io.milvus.param.index.CreateIndexParam;
+import io.milvus.response.QueryResultsWrapper;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class NullAndDefaultExample {
+    private static final String COLLECTION_NAME = "java_sdk_example_nullable_v1";
+    private static final String ID_FIELD = "id";
+    private static final String VECTOR_FIELD = "vector";
+    private static final Integer VECTOR_DIM = 128;
+
+    private static void queryWithExpr(MilvusClient client, String expr) {
+        R<QueryResults> queryRet = client.query(QueryParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withExpr(expr)
+                .addOutField("nullable_test")
+                .addOutField("default_test")
+                .addOutField("nullable_default")
+                .build());
+        QueryResultsWrapper queryWrapper = new QueryResultsWrapper(queryRet.getData());
+        System.out.println("\nQuery with expression: " + expr);
+        List<QueryResultsWrapper.RowRecord> records = queryWrapper.getRowRecords();
+        for (QueryResultsWrapper.RowRecord record : records) {
+            System.out.println(record);
+        }
+        System.out.printf("%d items matched%n", records.size());
+        System.out.println("=============================================================");
+    }
+
+    public static void main(String[] args) {
+        // Connect to Milvus server. Replace the "localhost" and port with your Milvus server address.
+        MilvusServiceClient client = new MilvusServiceClient(ConnectParam.newBuilder()
+                .withHost("localhost")
+                .withPort(19530)
+                .build());
+
+        // Define fields
+        List<FieldType> fieldsSchema = Arrays.asList(
+                FieldType.newBuilder()
+                        .withName(ID_FIELD)
+                        .withDataType(DataType.Int64)
+                        .withPrimaryKey(true)
+                        .withAutoID(false)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName(VECTOR_FIELD)
+                        .withDataType(DataType.FloatVector)
+                        .withDimension(VECTOR_DIM)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName("nullable_test")
+                        .withDataType(DataType.Int64)
+                        .withNullable(true)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName("default_test")
+                        .withDataType(DataType.Double)
+                        .withDefaultValue(3.1415)
+                        .build(),
+                FieldType.newBuilder()
+                        .withName("nullable_default")
+                        .withDataType(DataType.VarChar)
+                        .withMaxLength(64)
+                        .withDefaultValue("I am default value")
+                        .withNullable(true)
+                        .build()
+        );
+
+        // Drop the collection if exists
+        client.dropCollection(DropCollectionParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+
+        // Create the collection
+        R<RpcStatus> ret = client.createCollection(CreateCollectionParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldTypes(fieldsSchema)
+                .build());
+        if (ret.getStatus() != R.Status.Success.getCode()) {
+            throw new RuntimeException("Failed to create collection! Error: " + ret.getMessage());
+        }
+
+        // Specify an index type on the vector field.
+        ret = client.createIndex(CreateIndexParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withFieldName(VECTOR_FIELD)
+                .withIndexType(IndexType.FLAT)
+                .withMetricType(MetricType.L2)
+                .build());
+        if (ret.getStatus() != R.Status.Success.getCode()) {
+            throw new RuntimeException("Failed to create index on vector field! Error: " + ret.getMessage());
+        }
+
+        // Call loadCollection() to enable automatically loading data into memory for searching
+        client.loadCollection(LoadCollectionParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .build());
+
+        System.out.println("Collection created");
+
+        // Insert 10 records into the collection
+        Gson gson = new Gson();
+        List<JsonObject> rows = new ArrayList<>();
+        for (int i = 0; i < 10; ++i) {
+            JsonObject row = new JsonObject();
+            row.addProperty(ID_FIELD, i);
+            row.add(VECTOR_FIELD, gson.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
+            // half of values are null
+            if ((i % 2 == 0)) {
+                row.addProperty("nullable_test", i);
+            } else {
+                row.add("nullable_test", JsonNull.INSTANCE);
+            }
+
+            // some values are default value
+            if (i%3==0) {
+                row.addProperty("default_test", 1.0);
+            }
+
+            // some values are null, some values are default value
+            if (i > 5) {
+                if ((i % 2 == 0)) {
+                    row.addProperty("nullable_default", String.format("val_%d", i));
+                } else {
+                    // if default value is set, null value will be replaced by default value
+                    row.add("nullable_default", JsonNull.INSTANCE);
+                }
+            }
+
+            rows.add(row);
+        }
+
+        R<MutationResult> insertRet = client.insert(InsertParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withRows(rows)
+                .build());
+        if (insertRet.getStatus() != R.Status.Success.getCode()) {
+            throw new RuntimeException("Failed to insert! Error: " + insertRet.getMessage());
+        }
+
+        // Get row count
+        R<QueryResults> queryRet = client.query(QueryParam.newBuilder()
+                .withCollectionName(COLLECTION_NAME)
+                .withExpr("")
+                .addOutField("count(*)")
+                .withConsistencyLevel(ConsistencyLevelEnum.STRONG)
+                .build());
+        QueryResultsWrapper wrapper = new QueryResultsWrapper(queryRet.getData());
+        long rowCount = (long)wrapper.getFieldWrapper("count(*)").getFieldData().get(0);
+        System.out.printf("%d rows in collection\n", rowCount);
+
+        // Query by filtering expression
+        queryWithExpr(client, "id >= 0"); // show all items
+        queryWithExpr(client, "nullable_test >= 0");
+        queryWithExpr(client, "default_test == 3.1415");
+        queryWithExpr(client, "nullable_default != \"I am default value\"");
+    }
+}

+ 142 - 0
examples/main/java/io/milvus/v2/ArrayFieldExample.java

@@ -0,0 +1,142 @@
+package io.milvus.v2;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import io.milvus.common.utils.JsonUtils;
+import io.milvus.v1.CommonUtils;
+import io.milvus.v2.client.ConnectConfig;
+import io.milvus.v2.client.MilvusClientV2;
+import io.milvus.v2.common.ConsistencyLevel;
+import io.milvus.v2.common.DataType;
+import io.milvus.v2.common.IndexParam;
+import io.milvus.v2.service.collection.request.AddFieldReq;
+import io.milvus.v2.service.collection.request.CreateCollectionReq;
+import io.milvus.v2.service.collection.request.DropCollectionReq;
+import io.milvus.v2.service.vector.request.InsertReq;
+import io.milvus.v2.service.vector.request.QueryReq;
+import io.milvus.v2.service.vector.response.QueryResp;
+
+import java.util.*;
+
+public class ArrayFieldExample {
+    private static final String COLLECTION_NAME = "java_sdk_example_array_v2";
+    private static final String ID_FIELD = "id";
+    private static final String VECTOR_FIELD = "vector";
+    private static final Integer VECTOR_DIM = 128;
+
+    private static void queryWithExpr(MilvusClientV2 client, String expr) {
+        QueryResp queryRet = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter(expr)
+                .outputFields(Arrays.asList("array_int32", "array_varchar"))
+                .build());
+        System.out.println("\nQuery with expression: " + expr);
+        List<QueryResp.QueryResult> records = queryRet.getQueryResults();
+        for (QueryResp.QueryResult record : records) {
+            System.out.println(record.getEntity());
+        }
+        System.out.printf("%d items matched%n", records.size());
+        System.out.println("=============================================================");
+    }
+
+    public static void main(String[] args) {
+        ConnectConfig config = ConnectConfig.builder()
+                .uri("http://localhost:19530")
+                .build();
+        MilvusClientV2 client = new MilvusClientV2(config);
+
+        // Drop collection if exists
+        client.dropCollection(DropCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .build());
+
+        // Create collection
+        CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
+                .build();
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName(ID_FIELD)
+                .dataType(DataType.Int64)
+                .isPrimaryKey(true)
+                .autoID(true)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName(VECTOR_FIELD)
+                .dataType(DataType.FloatVector)
+                .dimension(VECTOR_DIM)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName("array_int32")
+                .dataType(DataType.Array)
+                .elementType(DataType.Int32)
+                .maxCapacity(10)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName("array_varchar")
+                .dataType(DataType.Array)
+                .elementType(DataType.VarChar)
+                .maxCapacity(10)
+                .maxLength(100)
+                .build());
+
+        List<IndexParam> indexes = new ArrayList<>();
+        indexes.add(IndexParam.builder()
+                .fieldName(VECTOR_FIELD)
+                .indexType(IndexParam.IndexType.FLAT)
+                .metricType(IndexParam.MetricType.COSINE)
+                .build());
+
+        CreateCollectionReq requestCreate = CreateCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .collectionSchema(collectionSchema)
+                .indexParams(indexes)
+                .consistencyLevel(ConsistencyLevel.BOUNDED)
+                .build();
+        client.createCollection(requestCreate);
+        System.out.println("Collection created");
+
+        // Insert rows
+        Random random = new Random();
+        int rowCount = 100;
+        Gson gson = new Gson();
+        List<JsonObject> rows = new ArrayList<>();
+        for (int i = 0; i < rowCount; i++) {
+            JsonObject row = new JsonObject();
+            row.add(VECTOR_FIELD, gson.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
+
+            List<Integer> intArray = new ArrayList<>();
+            List<String> strArray = new ArrayList<>();
+            int capacity = random.nextInt(5) + 5;
+            for (int k = 0; k < capacity; k++) {
+                intArray.add((i+k)%100);
+                strArray.add(String.format("string-%d-%d", i, k));
+            }
+            row.add("array_int32", JsonUtils.toJsonTree(intArray).getAsJsonArray());
+            row.add("array_varchar", JsonUtils.toJsonTree(strArray).getAsJsonArray());
+            rows.add(row);
+        }
+
+        client.insert(InsertReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .data(rows)
+                .build());
+
+        // Get row count, set ConsistencyLevel.STRONG to sync the data to query node so that data is visible
+        QueryResp countR = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter("")
+                .outputFields(Collections.singletonList("count(*)"))
+                .consistencyLevel(ConsistencyLevel.STRONG)
+                .build());
+        System.out.printf("%d rows in collection\n", (long)countR.getQueryResults().get(0).getEntity().get("count(*)"));
+
+        // Query by filtering expression
+        queryWithExpr(client, "array_int32[0] == 99");
+        queryWithExpr(client, "array_int32[1] in [5, 10, 15]");
+        queryWithExpr(client, "array_varchar[0] like \"string-55%\"");
+        queryWithExpr(client, "array_contains(array_varchar, \"string-4-1\")");
+        queryWithExpr(client, "array_contains_any(array_int32, [3, 9])");
+        queryWithExpr(client, "array_contains_all(array_int32, [3, 9])");
+
+        client.close();
+    }
+}

+ 139 - 0
examples/main/java/io/milvus/v2/FullTextSearchExample.java

@@ -0,0 +1,139 @@
+package io.milvus.v2;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import io.milvus.common.clientenum.FunctionType;
+import io.milvus.v2.client.ConnectConfig;
+import io.milvus.v2.client.MilvusClientV2;
+import io.milvus.v2.common.ConsistencyLevel;
+import io.milvus.v2.common.DataType;
+import io.milvus.v2.common.IndexParam;
+import io.milvus.v2.service.collection.request.AddFieldReq;
+import io.milvus.v2.service.collection.request.CreateCollectionReq;
+import io.milvus.v2.service.collection.request.DropCollectionReq;
+import io.milvus.v2.service.collection.request.CreateCollectionReq.Function;
+import io.milvus.v2.service.vector.request.InsertReq;
+import io.milvus.v2.service.vector.request.QueryReq;
+import io.milvus.v2.service.vector.request.SearchReq;
+import io.milvus.v2.service.vector.request.data.EmbeddedText;
+import io.milvus.v2.service.vector.response.QueryResp;
+import io.milvus.v2.service.vector.response.SearchResp;
+
+import java.util.*;
+
+public class FullTextSearchExample {
+    private static final String COLLECTION_NAME = "java_sdk_example_text_match_v2";
+    private static final String ID_FIELD = "id";
+    private static final String VECTOR_FIELD = "vector";
+
+    private static void searchByText(MilvusClientV2 client, String text) {
+        // The text is tokenized inside server and turned into a sparse embedding to compare with the vector field
+        SearchResp searchResp = client.search(SearchReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .data(Collections.singletonList(new EmbeddedText(text)))
+                .topK(3)
+                .outputFields(Collections.singletonList("text"))
+                .build());
+        System.out.println("\nSearch by text: " + text);
+        List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
+        for (List<SearchResp.SearchResult> results : searchResults) {
+            for (SearchResp.SearchResult result : results) {
+                System.out.printf("ID: %d, Score: %f, %s\n", (long)result.getId(), result.getScore(), result.getEntity().toString());
+            }
+        }
+        System.out.println("=============================================================");
+    }
+
+    public static void main(String[] args) {
+        ConnectConfig config = ConnectConfig.builder()
+                .uri("http://localhost:19530")
+                .build();
+        MilvusClientV2 client = new MilvusClientV2(config);
+
+        // Drop collection if exists
+        client.dropCollection(DropCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .build());
+
+        // Create collection
+        CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder()
+                .build();
+        schema.addField(AddFieldReq.builder()
+                .fieldName(ID_FIELD)
+                .dataType(DataType.Int64)
+                .isPrimaryKey(true)
+                .autoID(false)
+                .build());
+        schema.addField(AddFieldReq.builder()
+                .fieldName("text")
+                .dataType(DataType.VarChar)
+                .maxLength(65535)
+                .enableAnalyzer(true) // must enable this if you use Function
+                .build());
+        schema.addField(AddFieldReq.builder()
+                .fieldName(VECTOR_FIELD)
+                .dataType(DataType.SparseFloatVector)
+                .build());
+
+        // With this function, milvus will convert the strings of "text" field to sparse vectors of "vector" field
+        // by built-in tokenizer and analyzer
+        // Read the link for more info: https://milvus.io/docs/full-text-search.md
+        schema.addFunction(Function.builder()
+                .functionType(FunctionType.BM25)
+                .name("function_bm25")
+                .inputFieldNames(Collections.singletonList("text"))
+                .outputFieldNames(Collections.singletonList(VECTOR_FIELD))
+                .build());
+
+        List<IndexParam> indexes = new ArrayList<>();
+        indexes.add(IndexParam.builder()
+                .fieldName(VECTOR_FIELD)
+                .indexType(IndexParam.IndexType.SPARSE_INVERTED_INDEX)
+                .metricType(IndexParam.MetricType.BM25) // to use full text search, metric type must be "BM25"
+                .build());
+
+        CreateCollectionReq requestCreate = CreateCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .collectionSchema(schema)
+                .indexParams(indexes)
+                .consistencyLevel(ConsistencyLevel.BOUNDED)
+                .build();
+        client.createCollection(requestCreate);
+        System.out.println("Collection created");
+
+        // Insert rows
+        Gson gson = new Gson();
+        List<JsonObject> rows = Arrays.asList(
+                gson.fromJson("{\"id\": 0, \"text\": \"Milvus is an open-source vector database\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 1, \"text\": \"AI applications help people better life\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 2, \"text\": \"Will the electric car replace gas-powered car?\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 3, \"text\": \"LangChain is a composable framework to build with LLMs. Milvus is integrated into LangChain.\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 4, \"text\": \"RAG is the process of optimizing the output of a large language model\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 5, \"text\": \"Newton is one of the greatest scientist of human history\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 6, \"text\": \"Metric type L2 is Euclidean distance\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 7, \"text\": \"Embeddings represent real-world objects, like words, images, or videos, in a form that computers can process.\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 8, \"text\": \"The moon is 384,400 km distance away from earth\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 9, \"text\": \"Milvus supports L2 distance and IP similarity for float vector.\"}", JsonObject.class)
+        );
+
+        client.insert(InsertReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .data(rows)
+                .build());
+
+        // Get row count, set ConsistencyLevel.STRONG to sync the data to query node so that data is visible
+        QueryResp countR = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter("")
+                .outputFields(Collections.singletonList("count(*)"))
+                .consistencyLevel(ConsistencyLevel.STRONG)
+                .build());
+        System.out.printf("%d rows in collection\n", (long)countR.getQueryResults().get(0).getEntity().get("count(*)"));
+
+        // Query by filtering expression
+        searchByText(client, "moon and earth distance");
+        searchByText(client, "Milvus vector database");
+
+        client.close();
+    }
+}

+ 156 - 0
examples/main/java/io/milvus/v2/NullAndDefaultExample.java

@@ -0,0 +1,156 @@
+package io.milvus.v2;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import io.milvus.v1.CommonUtils;
+import io.milvus.v2.client.ConnectConfig;
+import io.milvus.v2.client.MilvusClientV2;
+import io.milvus.v2.common.ConsistencyLevel;
+import io.milvus.v2.common.DataType;
+import io.milvus.v2.common.IndexParam;
+import io.milvus.v2.service.collection.request.AddFieldReq;
+import io.milvus.v2.service.collection.request.CreateCollectionReq;
+import io.milvus.v2.service.collection.request.DropCollectionReq;
+import io.milvus.v2.service.vector.request.InsertReq;
+import io.milvus.v2.service.vector.request.QueryReq;
+import io.milvus.v2.service.vector.response.QueryResp;
+
+import java.util.*;
+
+public class NullAndDefaultExample {
+    private static final String COLLECTION_NAME = "java_sdk_example_nullable_v2";
+    private static final String ID_FIELD = "id";
+    private static final String VECTOR_FIELD = "vector";
+    private static final Integer VECTOR_DIM = 128;
+
+    private static void queryWithExpr(MilvusClientV2 client, String expr) {
+        QueryResp queryRet = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter(expr)
+                .outputFields(Arrays.asList("nullable_test", "default_test", "nullable_default"))
+                .build());
+        System.out.println("\nQuery with expression: " + expr);
+        List<QueryResp.QueryResult> records = queryRet.getQueryResults();
+        for (QueryResp.QueryResult record : records) {
+            System.out.println(record.getEntity());
+        }
+        System.out.printf("%d items matched%n", records.size());
+        System.out.println("=============================================================");
+    }
+
+    public static void main(String[] args) {
+        ConnectConfig config = ConnectConfig.builder()
+                .uri("http://localhost:19530")
+                .build();
+        MilvusClientV2 client = new MilvusClientV2(config);
+
+        // Drop collection if exists
+        client.dropCollection(DropCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .build());
+
+        // Create collection
+        CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
+                .build();
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName(ID_FIELD)
+                .dataType(DataType.Int64)
+                .isPrimaryKey(true)
+                .autoID(false)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName(VECTOR_FIELD)
+                .dataType(DataType.FloatVector)
+                .dimension(VECTOR_DIM)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName("nullable_test")
+                .dataType(DataType.Int32)
+                .isNullable(true)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName("default_test")
+                .dataType(DataType.Double)
+                .defaultValue(3.1415)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName("nullable_default")
+                .dataType(DataType.VarChar)
+                .maxLength(100)
+                .isNullable(true)
+                .defaultValue("I am default value")
+                .build());
+
+        List<IndexParam> indexes = new ArrayList<>();
+        indexes.add(IndexParam.builder()
+                .fieldName(VECTOR_FIELD)
+                .indexType(IndexParam.IndexType.FLAT)
+                .metricType(IndexParam.MetricType.COSINE)
+                .build());
+
+        CreateCollectionReq requestCreate = CreateCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .collectionSchema(collectionSchema)
+                .indexParams(indexes)
+                .consistencyLevel(ConsistencyLevel.BOUNDED)
+                .build();
+        client.createCollection(requestCreate);
+        System.out.println("Collection created");
+
+        // Insert rows
+        Gson gson = new Gson();
+        List<JsonObject> rows = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            JsonObject row = new JsonObject();
+            row.addProperty(ID_FIELD, i);
+            row.add(VECTOR_FIELD, gson.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
+
+            // half of values are null
+            if ((i % 2 == 0)) {
+                row.addProperty("nullable_test", i);
+            } else {
+                row.add("nullable_test", JsonNull.INSTANCE);
+            }
+
+            // some values are default value
+            if (i%3==0) {
+                row.addProperty("default_test", 1.0);
+            }
+
+            // some values are null, some values are default value
+            if (i > 5) {
+                if ((i % 2 == 0)) {
+                    row.addProperty("nullable_default", String.format("val_%d", i));
+                } else {
+                    // if default value is set, null value will be replaced by default value
+                    row.add("nullable_default", JsonNull.INSTANCE);
+                }
+            }
+
+            rows.add(row);
+        }
+
+        client.insert(InsertReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .data(rows)
+                .build());
+
+        // Get row count, set ConsistencyLevel.STRONG to sync the data to query node so that data is visible
+        QueryResp countR = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter("")
+                .outputFields(Collections.singletonList("count(*)"))
+                .consistencyLevel(ConsistencyLevel.STRONG)
+                .build());
+        System.out.printf("%d rows in collection\n", (long)countR.getQueryResults().get(0).getEntity().get("count(*)"));
+
+        // Query by filtering expression
+        queryWithExpr(client, "id >= 0"); // show all items
+        queryWithExpr(client, "nullable_test >= 0");
+        queryWithExpr(client, "default_test == 3.1415");
+        queryWithExpr(client, "nullable_default != \"I am default value\"");
+
+        client.close();
+    }
+}

+ 160 - 0
examples/main/java/io/milvus/v2/TextMatchExample.java

@@ -0,0 +1,160 @@
+package io.milvus.v2;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import io.milvus.v1.CommonUtils;
+import io.milvus.v2.client.ConnectConfig;
+import io.milvus.v2.client.MilvusClientV2;
+import io.milvus.v2.common.ConsistencyLevel;
+import io.milvus.v2.common.DataType;
+import io.milvus.v2.common.IndexParam;
+import io.milvus.v2.service.collection.request.AddFieldReq;
+import io.milvus.v2.service.collection.request.CreateCollectionReq;
+import io.milvus.v2.service.collection.request.DropCollectionReq;
+import io.milvus.v2.service.vector.request.InsertReq;
+import io.milvus.v2.service.vector.request.QueryReq;
+import io.milvus.v2.service.vector.request.SearchReq;
+import io.milvus.v2.service.vector.request.data.FloatVec;
+import io.milvus.v2.service.vector.response.QueryResp;
+import io.milvus.v2.service.vector.response.SearchResp;
+
+import java.util.*;
+
+public class TextMatchExample {
+    private static final String COLLECTION_NAME = "java_sdk_example_text_match_v2";
+    private static final String ID_FIELD = "id";
+    private static final String VECTOR_FIELD = "vector";
+    private static final Integer VECTOR_DIM = 128;
+
+    private static void queryWithFilter(MilvusClientV2 client, String filter) {
+        QueryResp queryRet = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter(filter)
+                .outputFields(Collections.singletonList("text"))
+                .build());
+        System.out.println("\nQuery with filter: " + filter);
+        List<QueryResp.QueryResult> records = queryRet.getQueryResults();
+        for (QueryResp.QueryResult record : records) {
+            System.out.println(record.getEntity());
+        }
+        System.out.printf("%d items matched%n", records.size());
+        System.out.println("=============================================================");
+    }
+
+    private static void searchWithFilter(MilvusClientV2 client, String filter) {
+        SearchResp searchResp = client.search(SearchReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .data(Collections.singletonList(new FloatVec(CommonUtils.generateFloatVector(VECTOR_DIM))))
+                .filter(filter)
+                .topK(10)
+                .outputFields(Collections.singletonList("text"))
+                .build());
+        System.out.println("\nSearch by filter: " + filter);
+        List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
+        for (List<SearchResp.SearchResult> results : searchResults) {
+            for (SearchResp.SearchResult result : results) {
+                System.out.printf("ID: %d, Score: %f, %s\n", (long)result.getId(), result.getScore(), result.getEntity().toString());
+            }
+        }
+        System.out.println("=============================================================");
+    }
+
+    public static void main(String[] args) {
+        ConnectConfig config = ConnectConfig.builder()
+                .uri("http://localhost:19530")
+                .build();
+        MilvusClientV2 client = new MilvusClientV2(config);
+
+        // Drop collection if exists
+        client.dropCollection(DropCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .build());
+
+        // Create collection
+        CreateCollectionReq.CollectionSchema collectionSchema = CreateCollectionReq.CollectionSchema.builder()
+                .build();
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName(ID_FIELD)
+                .dataType(DataType.Int64)
+                .isPrimaryKey(true)
+                .autoID(false)
+                .build());
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName(VECTOR_FIELD)
+                .dataType(DataType.FloatVector)
+                .dimension(VECTOR_DIM)
+                .build());
+        Map<String, Object> analyzerParams = new HashMap<>();
+        analyzerParams.put("type", "english");
+        collectionSchema.addField(AddFieldReq.builder()
+                .fieldName("text")
+                .dataType(DataType.VarChar)
+                .maxLength(1000)
+                .enableAnalyzer(true)
+                .analyzerParams(analyzerParams)
+                .enableMatch(true) // must enable this if you use TextMatch
+                .build());
+
+        List<IndexParam> indexes = new ArrayList<>();
+        indexes.add(IndexParam.builder()
+                .fieldName(VECTOR_FIELD)
+                .indexType(IndexParam.IndexType.FLAT)
+                .metricType(IndexParam.MetricType.L2)
+                .build());
+
+        CreateCollectionReq requestCreate = CreateCollectionReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .collectionSchema(collectionSchema)
+                .indexParams(indexes)
+                .consistencyLevel(ConsistencyLevel.BOUNDED)
+                .build();
+        client.createCollection(requestCreate);
+        System.out.println("Collection created");
+
+        // Insert rows
+        Gson gson = new Gson();
+        List<JsonObject> rows = Arrays.asList(
+                gson.fromJson("{\"id\": 0, \"text\": \"Milvus is an open-source vector database\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 1, \"text\": \"AI applications help people better life\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 2, \"text\": \"Will the electric car replace gas-powered car?\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 3, \"text\": \"LangChain is a composable framework to build with LLMs. Milvus is integrated into LangChain.\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 4, \"text\": \"RAG is the process of optimizing the output of a large language model\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 5, \"text\": \"Newton is one of the greatest scientist of human history\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 6, \"text\": \"Metric type L2 is Euclidean distance\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 7, \"text\": \"Embeddings represent real-world objects, like words, images, or videos, in a form that computers can process.\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 8, \"text\": \"The moon is 384,400 km distance away from earth\"}", JsonObject.class),
+                gson.fromJson("{\"id\": 9, \"text\": \"Milvus supports L2 distance and IP similarity for float vector.\"}", JsonObject.class)
+        );
+
+        // TextMatch is keyword filtering, here we just fill the vector field by random vectors
+        for (JsonObject obj : rows) {
+            obj.add(VECTOR_FIELD, gson.toJsonTree(CommonUtils.generateFloatVector(VECTOR_DIM)));
+        }
+
+        client.insert(InsertReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .data(rows)
+                .build());
+
+        // Get row count, set ConsistencyLevel.STRONG to sync the data to query node so that data is visible
+        QueryResp countR = client.query(QueryReq.builder()
+                .collectionName(COLLECTION_NAME)
+                .filter("")
+                .outputFields(Collections.singletonList("count(*)"))
+                .consistencyLevel(ConsistencyLevel.STRONG)
+                .build());
+        System.out.printf("%d rows in collection\n", (long)countR.getQueryResults().get(0).getEntity().get("count(*)"));
+
+        // Query by keyword filtering expression
+        queryWithFilter(client, "TEXT_MATCH(text, \"distance\")");
+        queryWithFilter(client, "TEXT_MATCH(text, \"Milvus\") or TEXT_MATCH(text, \"distance\")");
+        queryWithFilter(client, "TEXT_MATCH(text, \"Euclidean\") and TEXT_MATCH(text, \"distance\")");
+
+        // Search by keyword filtering expression
+        searchWithFilter(client, "TEXT_MATCH(text, \"distance\")");
+        searchWithFilter(client, "TEXT_MATCH(text, \"Euclidean distance\")");
+        searchWithFilter(client, "TEXT_MATCH(text, \"vector database\")");
+
+        client.close();
+    }
+}