Repository: milvus-io/milvus-sdk-go
Pull request #350 (2022-11-21 10:54:54)

Add query and pagination
See also #319 

/kind enhancement

Signed-off-by: Congqi Xia <congqi.xia@zilliz.com>

sre-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/milvus-io/milvus-sdk-go/pull/350#" title="Author self-approved">congqixia</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=milvus-io%2Fmilvus-sdk-go).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/milvus-io/milvus-sdk-go/blob/master/OWNERS)~~ [congqixia]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) Report
> Merging [#350](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) (60aef80) into [master](https://codecov.io/gh/milvus-io/milvus-sdk-go/commit/8f2a762916a3dbdbe89af15e6fcde6ec871f58c3?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) (8f2a762) will **increase** coverage by `0.19%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350/graphs/tree.svg?width=650&height=150&src=pr&token=WJK43PV390&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io)](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io)

```diff
@@            Coverage Diff             @@
##           master     #350      +/-   ##
==========================================
+ Coverage   84.29%   84.48%   +0.19%     
==========================================
  Files          27       27              
  Lines        3151     3165      +14     
==========================================
+ Hits         2656     2674      +18     
+ Misses        401      399       -2     
+ Partials       94       92       -2     
```


| [Impacted Files](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) | Coverage Δ | |
|---|---|---|
| [client/client.go](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2NsaWVudC5nbw==) | `75.80% <ø> (ø)` | |
| [client/client\_grpc\_data.go](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2NsaWVudF9ncnBjX2RhdGEuZ28=) | `72.56% <100.00%> (+0.98%)` | :arrow_up: |
| [client/client\_grpc\_options.go](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2NsaWVudF9ncnBjX29wdGlvbnMuZ28=) | `81.81% <100.00%> (+1.81%)` | :arrow_up: |
| [client/client\_grpc\_collection.go](https://codecov.io/gh/milvus-io/milvus-sdk-go/pull/350/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2NsaWVudF9ncnBjX2NvbGxlY3Rpb24uZ28=) | `86.38% <0.00%> (+0.85%)` | :arrow_up: |

weiliu1031: /lgtm

Patch:
diff --git a/client/client.go b/client/client.go
index 90502ea..2ae5f5e 100644
--- a/client/client.go
+++ b/client/client.go
@@ -118,8 +118,10 @@ type Client interface {
 	// Search search with bool expression
 	Search(ctx context.Context, collName string, partitions []string,
 		expr string, outputFields []string, vectors []entity.Vector, vectorField string, metricType entity.MetricType, topK int, sp entity.SearchParam, opts ...SearchQueryOptionFunc) ([]SearchResult, error)
-	// QueryByPks query record by specified primary key(s)
+	// QueryByPks query record by specified primary key(s).
 	QueryByPks(ctx context.Context, collectionName string, partitionNames []string, ids entity.Column, outputFields []string, opts ...SearchQueryOptionFunc) ([]entity.Column, error)
+	// Query performs query records with boolean expression.
+	Query(ctx context.Context, collectionName string, partitionNames []string, expr string, outputFields []string, opts ...SearchQueryOptionFunc) ([]entity.Column, error)
 
 	// CalcDistance calculate the distance between vectors specified by ids or provided
 	CalcDistance(ctx context.Context, collName string, partitions []string,
diff --git a/client/client_grpc_data.go b/client/client_grpc_data.go
index a727cbf..06d17bb 100644
--- a/client/client_grpc_data.go
+++ b/client/client_grpc_data.go
@@ -28,6 +28,11 @@ import (
 	"github.com/milvus-io/milvus-sdk-go/v2/entity"
 )
 
+const (
+	offsetKey = `offset`
+	limitKey  = `limit`
+)
+
 // Insert Index  into collection with column-based format
 // collName is the collection name
 // partitionName is the partition to insert, if not specified(empty), default partition will be used
@@ -234,7 +239,7 @@ func (c *GrpcClient) Search(ctx context.Context, collName string, partitions []s
 	if !ok {
 		c.DescribeCollection(ctx, collName)
 	}
-	option, err := MakeSearchQueryOption(collName, opts...)
+	option, err := makeSearchQueryOption(collName, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -312,12 +317,24 @@ func (c *GrpcClient) QueryByPks(ctx context.Context, collectionName string, part
 
 	expr := PKs2Expr(ids)
 
+	return c.Query(ctx, collectionName, partitionNames, expr, outputFields, opts...)
+}
+
+// Query performs query by expression.
+func (c *GrpcClient) Query(ctx context.Context, collectionName string, partitionNames []string, expr string, outputFields []string, opts ...SearchQueryOptionFunc) ([]entity.Column, error) {
+	if c.Service == nil {
+		return nil, ErrClientNotReady
+	}
+
 	_, ok := MetaCache.getCollectionInfo(collectionName)
 	if !ok {
-		c.DescribeCollection(ctx, collectionName)
+		_, err := c.DescribeCollection(ctx, collectionName)
+		if err != nil {
+			return nil, err
+		}
 	}
 
-	option, err := MakeSearchQueryOption(collectionName, opts...)
+	option, err := makeSearchQueryOption(collectionName, opts...)
 	if err != nil {
 		return nil, err
 	}
@@ -331,6 +348,13 @@ func (c *GrpcClient) QueryByPks(ctx context.Context, collectionName string, part
 		GuaranteeTimestamp: option.GuaranteeTimestamp,
 		TravelTimestamp:    option.TravelTimestamp,
 	}
+	if option.Offset > 0 {
+		req.QueryParams = append(req.QueryParams, &common.KeyValuePair{Key: offsetKey, Value: strconv.FormatInt(option.Offset, 10)})
+	}
+	if option.Limit > 0 {
+		req.QueryParams = append(req.QueryParams, &common.KeyValuePair{Key: limitKey, Value: strconv.FormatInt(option.Limit, 10)})
+	}
+
 	resp, err := c.Service.Query(ctx, req)
 	if err != nil {
 		return nil, err
@@ -385,6 +409,7 @@ func prepareSearchRequest(collName string, partitions []string,
 		"params":        string(bs),
 		"metric_type":   string(metricType),
 		"round_decimal": "-1",
+		offsetKey:       fmt.Sprintf("%d", opt.Offset),
 	})
 	req := &server.SearchRequest{
 		DbName:             "",
diff --git a/client/client_grpc_options.go b/client/client_grpc_options.go
index d4f7ef5..c65a755 100644
--- a/client/client_grpc_options.go
+++ b/client/client_grpc_options.go
@@ -41,14 +41,32 @@ func WithReplicaNumber(rn int32) LoadCollectionOption {
 
 // SearchQueryOption is an option of search/query request
 type SearchQueryOption struct {
+	// Consistency Level & Time travel
 	ConsistencyLevel   entity.ConsistencyLevel
 	GuaranteeTimestamp uint64
 	TravelTimestamp    uint64
+	// Pagination
+	Limit  int64
+	Offset int64
 }
 
 // SearchQueryOptionFunc is a function which modifies SearchOption
 type SearchQueryOptionFunc func(option *SearchQueryOption)
 
+// WithOffset returns search/query option with offset.
+func WithOffset(offset int64) SearchQueryOptionFunc {
+	return func(option *SearchQueryOption) {
+		option.Offset = offset
+	}
+}
+
+// WithLimit returns search/query option with limit.
+func WithLimit(limit int64) SearchQueryOptionFunc {
+	return func(option *SearchQueryOption) {
+		option.Limit = limit
+	}
+}
+
 // WithSearchQueryConsistencyLevel specifies consistency level
 func WithSearchQueryConsistencyLevel(cl entity.ConsistencyLevel) SearchQueryOptionFunc {
 	return func(option *SearchQueryOption) {
@@ -70,7 +88,7 @@ func WithTravelTimestamp(tt uint64) SearchQueryOptionFunc {
 	}
 }
 
-func MakeSearchQueryOption(collName string, opts ...SearchQueryOptionFunc) (*SearchQueryOption, error) {
+func makeSearchQueryOption(collName string, opts ...SearchQueryOptionFunc) (*SearchQueryOption, error) {
 	opt := &SearchQueryOption{
 		ConsistencyLevel: entity.ClBounded, // default
 	}


Test patch:
diff --git a/client/client_grpc_collection_test.go b/client/client_grpc_collection_test.go
index eaccc02..e322aa4 100644
--- a/client/client_grpc_collection_test.go
+++ b/client/client_grpc_collection_test.go
@@ -489,7 +489,7 @@ func describeCollectionInjection(t *testing.T, collID int64, collName string, sc
 			return resp, err
 		}
 
-		assert.Equal(t, testCollectionName, req.GetCollectionName())
+		assert.Equal(t, collName, req.GetCollectionName())
 
 		sch := sch
 		resp.Schema = sch.ProtoMessage()
diff --git a/client/client_grpc_data_test.go b/client/client_grpc_data_test.go
index 53e6809..f110c26 100644
--- a/client/client_grpc_data_test.go
+++ b/client/client_grpc_data_test.go
@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"github.com/golang/protobuf/proto"
+	"github.com/milvus-io/milvus-proto/go-api/commonpb"
 	common "github.com/milvus-io/milvus-proto/go-api/commonpb"
 	server "github.com/milvus-io/milvus-proto/go-api/milvuspb"
 	schema "github.com/milvus-io/milvus-proto/go-api/schemapb"
@@ -350,6 +351,287 @@ func TestGrpcSearch(t *testing.T) {
 	})
 }
 
+func TestGrpcQuery(t *testing.T) {
+	ctx := context.Background()
+	c := testClient(ctx, t)
+	partName := "testPart"
+
+	t.Run("normal query", func(t *testing.T) {
+		mock.SetInjection(MHasCollection, hasCollectionDefault)
+		mock.SetInjection(MHasPartition, hasPartitionInjection(t, testCollectionName, false, partName))
+		defer mock.DelInjection(MHasPartition)
+
+		mock.SetInjection(MQuery, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			req, ok := raw.(*server.QueryRequest)
+			if !ok {
+				t.FailNow()
+			}
+			assert.Equal(t, testCollectionName, req.GetCollectionName())
+			if len(req.GetPartitionNames()) > 0 {
+				assert.Equal(t, partName, req.GetPartitionNames()[0])
+			}
+
+			resp := &server.QueryResults{}
+			s, err := SuccessStatus()
+			resp.Status = s
+			resp.FieldsData = []*schema.FieldData{
+				{
+					Type:      schema.DataType_Int64,
+					FieldName: "int64",
+					Field: &schema.FieldData_Scalars{
+						Scalars: &schema.ScalarField{
+							Data: &schema.ScalarField_LongData{
+								LongData: &schema.LongArray{
+									Data: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
+								},
+							},
+						},
+					},
+				},
+				{
+					Type:      schema.DataType_FloatVector,
+					FieldName: testVectorField,
+					Field: &schema.FieldData_Vectors{
+						Vectors: &schema.VectorField{
+							Dim: 1,
+							Data: &schema.VectorField_FloatVector{
+								FloatVector: &schema.FloatArray{
+									Data: []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0},
+								},
+							},
+						},
+					},
+				},
+			}
+
+			return resp, err
+		})
+		defer mock.DelInjection(MQuery)
+
+		columns, err := c.Query(ctx, testCollectionName, []string{partName}, "int64 in {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}", []string{testPrimaryField, testVectorField}, WithOffset(1), WithLimit(10))
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(columns))
+		assert.Equal(t, entity.FieldTypeInt64, columns[0].Type())
+		assert.Equal(t, entity.FieldTypeFloatVector, columns[1].Type())
+		assert.Equal(t, 10, columns[0].Len())
+
+		colInt64, ok := columns[0].(*entity.ColumnInt64)
+		assert.True(t, ok)
+		assert.ElementsMatch(t, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, colInt64.Data())
+
+		// query with options
+		columns, err = c.Query(ctx, testCollectionName, []string{partName}, "int64 in {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}", []string{"int64", testVectorField}, WithSearchQueryConsistencyLevel(entity.ClSession), WithTravelTimestamp(0))
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(columns))
+		assert.Equal(t, entity.FieldTypeInt64, columns[0].Type())
+		assert.Equal(t, entity.FieldTypeFloatVector, columns[1].Type())
+		assert.Equal(t, 10, columns[0].Len())
+
+		colInt64, ok = columns[0].(*entity.ColumnInt64)
+		assert.True(t, ok)
+		assert.ElementsMatch(t, []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, colInt64.Data())
+	})
+
+	t.Run("normal query varchar pks", func(t *testing.T) {
+		mock.SetInjection(MHasCollection, hasCollectionDefault)
+		mock.SetInjection(MHasPartition, hasPartitionInjection(t, testCollectionName, false, partName))
+		defer mock.DelInjection(MHasPartition)
+		mock.SetInjection(MDescribeCollection, describeCollectionInjection(t, testCollectionID, testCollectionName, varCharSchema()))
+		defer mock.SetInjection(MDescribeCollection, describeCollectionInjection(t, testCollectionID, testCollectionName, defaultSchema()))
+
+		mock.SetInjection(MQuery, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			req, ok := raw.(*server.QueryRequest)
+			if !ok {
+				t.FailNow()
+			}
+			assert.Equal(t, testCollectionName, req.GetCollectionName())
+			if len(req.GetPartitionNames()) > 0 {
+				assert.Equal(t, partName, req.GetPartitionNames()[0])
+			}
+
+			resp := &server.QueryResults{}
+			s, err := SuccessStatus()
+			resp.Status = s
+			resp.FieldsData = []*schema.FieldData{
+				{
+					Type:      schema.DataType_VarChar,
+					FieldName: "varchar",
+					Field: &schema.FieldData_Scalars{
+						Scalars: &schema.ScalarField{
+							Data: &schema.ScalarField_StringData{
+								StringData: &schema.StringArray{
+									Data: []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"},
+								},
+							},
+						},
+					},
+				},
+				{
+					Type:      schema.DataType_FloatVector,
+					FieldName: testVectorField,
+					Field: &schema.FieldData_Vectors{
+						Vectors: &schema.VectorField{
+							Dim: 1,
+							Data: &schema.VectorField_FloatVector{
+								FloatVector: &schema.FloatArray{
+									Data: []float32{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0},
+								},
+							},
+						},
+					},
+				},
+			}
+
+			return resp, err
+		})
+		defer mock.DelInjection(MQuery)
+
+		columns, err := c.Query(ctx, testCollectionName, []string{partName}, `varchar in {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}`, []string{"varchar", testVectorField})
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(columns))
+		assert.Equal(t, entity.FieldTypeVarChar, columns[0].Type())
+		assert.Equal(t, entity.FieldTypeFloatVector, columns[1].Type())
+		assert.Equal(t, 10, columns[0].Len())
+
+		colPK, ok := columns[0].(*entity.ColumnVarChar)
+		assert.True(t, ok)
+		assert.ElementsMatch(t, []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}, colPK.Data())
+	})
+
+	t.Run("Bad request querys", func(t *testing.T) {
+		mock.SetInjection(MHasCollection, hasCollectionDefault)
+		mock.SetInjection(MHasPartition, hasPartitionInjection(t, testCollectionName, false, partName))
+		defer mock.DelInjection(MHasPartition)
+		mock.SetInjection(MDescribeCollection, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			req, ok := raw.(*server.DescribeCollectionRequest)
+			resp := &server.DescribeCollectionResponse{}
+			if !ok {
+				s, err := BadRequestStatus()
+				resp.Status = s
+				return resp, err
+			}
+
+			if req.CollectionName != testCollectionName {
+				resp.Status = &commonpb.Status{
+					ErrorCode: commonpb.ErrorCode_CollectionNameNotFound,
+				}
+				return resp, nil
+			}
+			sch := defaultSchema()
+			resp.Schema = sch.ProtoMessage()
+			resp.CollectionID = testCollectionID
+
+			s, err := SuccessStatus()
+			resp.Status = s
+
+			return resp, err
+		})
+		defer mock.SetInjection(MDescribeCollection, describeCollectionInjection(t, testCollectionID, testCollectionName, defaultSchema()))
+
+		// non-exist collection
+		_, err := c.Query(ctx, "non-exists-collection", []string{}, "pk in {}", []string{})
+		assert.Error(t, err)
+	})
+
+	t.Run("Query Service error", func(t *testing.T) {
+		mock.SetInjection(MHasCollection, hasCollectionDefault)
+		mock.SetInjection(MHasPartition, hasPartitionInjection(t, testCollectionName, false, partName))
+		defer mock.DelInjection(MHasPartition)
+
+		mock.SetInjection(MQuery, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			_, ok := raw.(*server.QueryRequest)
+			if !ok {
+				t.FailNow()
+			}
+
+			resp := &server.QueryResults{}
+			return resp, errors.New("mocked error")
+		})
+		defer mock.DelInjection(MQuery)
+
+		_, err := c.Query(ctx, testCollectionName, []string{}, "int64 in {1}", []string{"*"})
+		assert.Error(t, err)
+
+		mock.SetInjection(MQuery, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			_, ok := raw.(*server.QueryRequest)
+			if !ok {
+				t.FailNow()
+			}
+
+			resp := &server.QueryResults{}
+			resp.Status = &common.Status{
+				ErrorCode: common.ErrorCode_UnexpectedError,
+				Reason:    "mocked error",
+			}
+			return resp, nil
+		})
+
+		_, err = c.Query(ctx, testCollectionName, []string{}, "int64 in {1}", []string{"*"})
+		assert.Error(t, err)
+
+		mock.SetInjection(MQuery, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			_, ok := raw.(*server.QueryRequest)
+			if !ok {
+				t.FailNow()
+			}
+
+			resp := &server.QueryResults{}
+			s, err := SuccessStatus()
+			resp.Status = s
+			resp.FieldsData = []*schema.FieldData{
+				{
+					Type:      schema.DataType_String,
+					FieldName: "int64",
+					Field: &schema.FieldData_Scalars{
+						Scalars: &schema.ScalarField{
+							Data: &schema.ScalarField_LongData{
+								LongData: &schema.LongArray{
+									Data: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
+								},
+							},
+						},
+					},
+				},
+			}
+
+			return resp, err
+		})
+		_, err = c.Query(ctx, testCollectionName, []string{}, "int64 in {1}", []string{"*"})
+		assert.Error(t, err)
+
+		mock.SetInjection(MQuery, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			_, ok := raw.(*server.QueryRequest)
+			if !ok {
+				t.FailNow()
+			}
+
+			resp := &server.QueryResults{}
+			s, err := SuccessStatus()
+			resp.Status = s
+			resp.FieldsData = []*schema.FieldData{
+				{
+					Type:      schema.DataType_FloatVector,
+					FieldName: "int64",
+					Field: &schema.FieldData_Scalars{
+						Scalars: &schema.ScalarField{
+							Data: &schema.ScalarField_LongData{
+								LongData: &schema.LongArray{
+									Data: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
+								},
+							},
+						},
+					},
+				},
+			}
+
+			return resp, err
+		})
+		_, err = c.Query(ctx, testCollectionName, []string{}, "int64 in {1}", []string{"*"})
+		assert.Error(t, err)
+	})
+
+}
+
 func TestGrpcQueryByPks(t *testing.T) {
 	ctx := context.Background()
 	c := testClient(ctx, t)
diff --git a/client/client_grpc_options_test.go b/client/client_grpc_options_test.go
index 6010893..d64a165 100644
--- a/client/client_grpc_options_test.go
+++ b/client/client_grpc_options_test.go
@@ -57,7 +57,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 	MetaCache.setCollectionInfo(c.Name, &cInfo)
 
 	t.Run("strong consistency", func(t *testing.T) {
-		opt, err := MakeSearchQueryOption(c.Name)
+		opt, err := makeSearchQueryOption(c.Name)
 		assert.Nil(t, err)
 		assert.NotNil(t, opt)
 		expected := &SearchQueryOption{
@@ -68,7 +68,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 	})
 
 	t.Run("session consistency", func(t *testing.T) {
-		opt, err := MakeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClSession))
+		opt, err := makeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClSession))
 		assert.Nil(t, err)
 		assert.NotNil(t, opt)
 		expected := &SearchQueryOption{
@@ -78,7 +78,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 		assert.Equal(t, expected, opt)
 
 		MetaCache.setSessionTs(c.Name, 99)
-		opt, err = MakeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClSession))
+		opt, err = makeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClSession))
 		assert.Nil(t, err)
 		assert.NotNil(t, opt)
 		expected = &SearchQueryOption{
@@ -89,7 +89,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 	})
 
 	t.Run("bounded consistency", func(t *testing.T) {
-		opt, err := MakeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClBounded))
+		opt, err := makeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClBounded))
 		assert.Nil(t, err)
 		assert.NotNil(t, opt)
 		expected := &SearchQueryOption{
@@ -100,7 +100,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 	})
 
 	t.Run("eventually consistency", func(t *testing.T) {
-		opt, err := MakeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClEventually))
+		opt, err := makeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClEventually))
 		assert.Nil(t, err)
 		assert.NotNil(t, opt)
 		expected := &SearchQueryOption{
@@ -111,7 +111,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 	})
 
 	t.Run("customized consistency", func(t *testing.T) {
-		opt, err := MakeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClCustomized), WithGuaranteeTimestamp(100))
+		opt, err := makeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClCustomized), WithGuaranteeTimestamp(100))
 		assert.Nil(t, err)
 		assert.NotNil(t, opt)
 		expected := &SearchQueryOption{
@@ -122,7 +122,7 @@ func TestMakeSearchQueryOption(t *testing.T) {
 	})
 
 	t.Run("guarantee timestamp sanity check", func(t *testing.T) {
-		_, err := MakeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClStrong), WithGuaranteeTimestamp(100))
+		_, err := makeSearchQueryOption(c.Name, WithSearchQueryConsistencyLevel(entity.ClStrong), WithGuaranteeTimestamp(100))
 		assert.Error(t, err)
 	})
 }