Repository: milvus-io/milvus-sdk-go
Pull request #471 (2023-05-26 03:23:48)

Improve ResultSet & Column Get methods
- Add GetAs(Int|Double|String|Bool) methods for all column
- Fix some warning in test cases
- Use GetColumn and GetAsXXX methods in dynamic schema example

/kind improvement

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/471#" 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://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) Report
> Merging [#471](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) (cada678) into [master](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/commit/104724accd7f4a7cfc82965d751d4fb29a36e6b4?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) (104724a) will **decrease** coverage by `0.72%`.
> The diff coverage is `3.22%`.

[![Impacted file tree graph](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471/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://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?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     #471      +/-   ##
==========================================
- Coverage   84.78%   84.06%   -0.72%     
==========================================
  Files          35       36       +1     
  Lines        3286     3314      +28     
==========================================
  Hits         2786     2786              
- Misses        397      425      +28     
  Partials      103      103              
```


| [Impacted Files](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?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://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2NsaWVudC5nbw==) | `67.50% <ø> (ø)` | |
| [entity/columns.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnMuZ28=) | `71.82% <0.00%> (-0.81%)` | :arrow_down: |
| [entity/columns\_conversion.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnNfY29udmVyc2lvbi5nbw==) | `0.00% <0.00%> (ø)` | |
| [entity/columns\_dynamic.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnNfZHluYW1pYy5nbw==) | `85.10% <0.00%> (-14.90%)` | :arrow_down: |
| [entity/columns\_json.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnNfanNvbi5nbw==) | `80.00% <0.00%> (-10.33%)` | :arrow_down: |
| [entity/columns\_scalar\_gen.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnNfc2NhbGFyX2dlbi5nbw==) | `87.50% <ø> (ø)` | |
| [entity/columns\_varchar.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnNfdmFyY2hhci5nbw==) | `82.35% <0.00%> (-7.97%)` | :arrow_down: |
| [entity/columns\_vector\_gen.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-ZW50aXR5L2NvbHVtbnNfdmVjdG9yX2dlbi5nbw==) | `89.65% <ø> (ø)` | |
| [client/partition.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/471?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L3BhcnRpdGlvbi5nbw==) | `84.25% <100.00%> (ø)` | |

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/471#" title="Author self-approved">congqixia</a>*, *<a href="https://github.com/milvus-io/milvus-sdk-go/pull/471#pullrequestreview-1445124307" title="LGTM">yah01</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":[]} -->

Patch:
diff --git a/client/client.go b/client/client.go
index c2c16ab..358d834 100644
--- a/client/client.go
+++ b/client/client.go
@@ -202,8 +202,10 @@ type SearchResult struct {
 	Err         error         // search error if any
 }
 
+// ResultSet is an alias type for column slice.
 type ResultSet []entity.Column
 
+// GetColumn returns column with provided field name.
 func (rs ResultSet) GetColumn(fieldName string) entity.Column {
 	for _, column := range rs {
 		if column.Name() == fieldName {
diff --git a/client/partition.go b/client/partition.go
index 8761233..5cba323 100644
--- a/client/partition.go
+++ b/client/partition.go
@@ -162,7 +162,7 @@ func (c *GrpcClient) LoadPartitions(ctx context.Context, collName string, partit
 	for _, partitionName := range partitionNames {
 		id, has := m[partitionName]
 		if !has {
-			return fmt.Errorf("Collection %s does not has partitions %s", collName, partitionName)
+			return fmt.Errorf("collection %s does not has partitions %s", collName, partitionName)
 		}
 		ids[id] = struct{}{}
 	}
diff --git a/entity/columns.go b/entity/columns.go
index ab9c620..7ce8d50 100644
--- a/entity/columns.go
+++ b/entity/columns.go
@@ -21,20 +21,8 @@ import (
 	"github.com/cockroachdb/errors"
 )
 
-var ErrDataTypeNotMatch = errors.New("data type not matched")
-
 //go:generate go run gen/gen.go
 
-type ColumnBase struct{}
-
-func (b ColumnBase) GetInt64() (int64, error) {
-	return 0, ErrDataTypeNotMatch
-}
-
-func (b ColumnBase) GetFloat64() (float64, error) {
-	return 0, ErrDataTypeNotMatch
-}
-
 // Column interface field type for column-based data frame
 type Column interface {
 	Name() string
@@ -43,6 +31,29 @@ type Column interface {
 	FieldData() *schema.FieldData
 	AppendValue(interface{}) error
 	Get(int) (interface{}, error)
+	GetAsInt64(int) (int64, error)
+	GetAsString(int) (string, error)
+	GetAsDouble(int) (float64, error)
+	GetAsBool(int) (bool, error)
+}
+
+// ColumnBase adds conversion methods support for fixed-type columns.
+type ColumnBase struct{}
+
+func (b ColumnBase) GetAsInt64(_ int) (int64, error) {
+	return 0, errors.New("conversion between fixed-type column not support")
+}
+
+func (b ColumnBase) GetAsString(_ int) (string, error) {
+	return "", errors.New("conversion between fixed-type column not support")
+}
+
+func (b ColumnBase) GetAsDouble(_ int) (float64, error) {
+	return 0, errors.New("conversion between fixed-type column not support")
+}
+
+func (b ColumnBase) GetAsBool(_ int) (bool, error) {
+	return false, errors.New("conversion between fixed-type column not support")
 }
 
 // Vector interface vector used int search
diff --git a/entity/columns_conversion.go b/entity/columns_conversion.go
new file mode 100644
index 0000000..7910cae
--- /dev/null
+++ b/entity/columns_conversion.go
@@ -0,0 +1,37 @@
+package entity
+
+func (c *ColumnInt8) GetAsInt64(idx int) (int64, error) {
+	v, err := c.ValueByIdx(idx)
+	return int64(v), err
+}
+
+func (c *ColumnInt16) GetAsInt64(idx int) (int64, error) {
+	v, err := c.ValueByIdx(idx)
+	return int64(v), err
+}
+
+func (c *ColumnInt32) GetAsInt64(idx int) (int64, error) {
+	v, err := c.ValueByIdx(idx)
+	return int64(v), err
+}
+
+func (c *ColumnInt64) GetAsInt64(idx int) (int64, error) {
+	return c.ValueByIdx(idx)
+}
+
+func (c *ColumnString) GetAsString(idx int) (string, error) {
+	return c.ValueByIdx(idx)
+}
+
+func (c *ColumnFloat) GetAsDouble(idx int) (float64, error) {
+	v, err := c.ValueByIdx(idx)
+	return float64(v), err
+}
+
+func (c *ColumnDouble) GetAsDouble(idx int) (float64, error) {
+	return c.ValueByIdx(idx)
+}
+
+func (c *ColumnBool) GetAsBool(idx int) (bool, error) {
+	return c.ValueByIdx(idx)
+}
diff --git a/entity/columns_dynamic.go b/entity/columns_dynamic.go
index e4a0183..a865b66 100644
--- a/entity/columns_dynamic.go
+++ b/entity/columns_dynamic.go
@@ -33,7 +33,21 @@ func (c *ColumnDynamic) Name() string {
 	return c.outputField
 }
 
-func (c *ColumnDynamic) GetInt64(idx int) (int64, error) {
+// Get returns element at idx as interface{}.
+// Overrides internal json column behavior, returns raw json data.
+func (c *ColumnDynamic) Get(idx int) (interface{}, error) {
+	bs, err := c.ColumnJSONBytes.ValueByIdx(idx)
+	if err != nil {
+		return 0, err
+	}
+	r := gjson.GetBytes(bs, c.outputField)
+	if !r.Exists() {
+		return 0, errors.New("column not has value")
+	}
+	return r.Raw, nil
+}
+
+func (c *ColumnDynamic) GetAsInt64(idx int) (int64, error) {
 	bs, err := c.ColumnJSONBytes.ValueByIdx(idx)
 	if err != nil {
 		return 0, err
@@ -48,7 +62,7 @@ func (c *ColumnDynamic) GetInt64(idx int) (int64, error) {
 	return r.Int(), nil
 }
 
-func (c *ColumnDynamic) GetString(idx int) (string, error) {
+func (c *ColumnDynamic) GetAsString(idx int) (string, error) {
 	bs, err := c.ColumnJSONBytes.ValueByIdx(idx)
 	if err != nil {
 		return "", err
@@ -63,7 +77,7 @@ func (c *ColumnDynamic) GetString(idx int) (string, error) {
 	return r.String(), nil
 }
 
-func (c *ColumnDynamic) GetBool(idx int) (bool, error) {
+func (c *ColumnDynamic) GetAsBool(idx int) (bool, error) {
 	bs, err := c.ColumnJSONBytes.ValueByIdx(idx)
 	if err != nil {
 		return false, err
@@ -78,7 +92,7 @@ func (c *ColumnDynamic) GetBool(idx int) (bool, error) {
 	return r.Bool(), nil
 }
 
-func (c *ColumnDynamic) GetDouble(idx int) (float64, error) {
+func (c *ColumnDynamic) GetAsDouble(idx int) (float64, error) {
 	bs, err := c.ColumnJSONBytes.ValueByIdx(idx)
 	if err != nil {
 		return 0, err
diff --git a/entity/columns_json.go b/entity/columns_json.go
index 41c7919..8cb2226 100644
--- a/entity/columns_json.go
+++ b/entity/columns_json.go
@@ -12,6 +12,7 @@ var _ (Column) = (*ColumnJSONBytes)(nil)
 // ColumnJSONBytes column type for JSON.
 // all items are marshaled json bytes.
 type ColumnJSONBytes struct {
+	ColumnBase
 	name      string
 	values    [][]byte
 	isDynamic bool
@@ -40,6 +41,14 @@ func (c *ColumnJSONBytes) Get(idx int) (interface{}, error) {
 	return c.values[idx], nil
 }
 
+func (c *ColumnJSONBytes) GetAsString(idx int) (string, error) {
+	bs, err := c.ValueByIdx(idx)
+	if err != nil {
+		return "", err
+	}
+	return string(bs), nil
+}
+
 // FieldData return column data mapped to schema.FieldData.
 func (c *ColumnJSONBytes) FieldData() *schema.FieldData {
 	fd := &schema.FieldData{
diff --git a/entity/columns_scalar_gen.go b/entity/columns_scalar_gen.go
index 48625c1..7378537 100755
--- a/entity/columns_scalar_gen.go
+++ b/entity/columns_scalar_gen.go
@@ -12,6 +12,7 @@ import (
 
 // ColumnBool generated columns type for Bool
 type ColumnBool struct {
+	ColumnBase
 	name   string
 	values []bool
 }
@@ -98,6 +99,7 @@ func NewColumnBool(name string, values []bool) *ColumnBool {
 
 // ColumnInt8 generated columns type for Int8
 type ColumnInt8 struct {
+	ColumnBase
 	name   string
 	values []int8
 }
@@ -184,6 +186,7 @@ func NewColumnInt8(name string, values []int8) *ColumnInt8 {
 
 // ColumnInt16 generated columns type for Int16
 type ColumnInt16 struct {
+	ColumnBase
 	name   string
 	values []int16
 }
@@ -270,6 +273,7 @@ func NewColumnInt16(name string, values []int16) *ColumnInt16 {
 
 // ColumnInt32 generated columns type for Int32
 type ColumnInt32 struct {
+	ColumnBase
 	name   string
 	values []int32
 }
@@ -356,6 +360,7 @@ func NewColumnInt32(name string, values []int32) *ColumnInt32 {
 
 // ColumnInt64 generated columns type for Int64
 type ColumnInt64 struct {
+	ColumnBase
 	name   string
 	values []int64
 }
@@ -442,6 +447,7 @@ func NewColumnInt64(name string, values []int64) *ColumnInt64 {
 
 // ColumnFloat generated columns type for Float
 type ColumnFloat struct {
+	ColumnBase
 	name   string
 	values []float32
 }
@@ -528,6 +534,7 @@ func NewColumnFloat(name string, values []float32) *ColumnFloat {
 
 // ColumnDouble generated columns type for Double
 type ColumnDouble struct {
+	ColumnBase
 	name   string
 	values []float64
 }
@@ -614,6 +621,7 @@ func NewColumnDouble(name string, values []float64) *ColumnDouble {
 
 // ColumnString generated columns type for String
 type ColumnString struct {
+	ColumnBase
 	name   string
 	values []string
 }
diff --git a/entity/columns_varchar.go b/entity/columns_varchar.go
index c000429..6873f80 100644
--- a/entity/columns_varchar.go
+++ b/entity/columns_varchar.go
@@ -9,6 +9,7 @@ import (
 
 // ColumnVarChar generated columns type for VarChar
 type ColumnVarChar struct {
+	ColumnBase
 	name   string
 	values []string
 }
@@ -36,6 +37,14 @@ func (c *ColumnVarChar) Get(idx int) (interface{}, error) {
 	return c.values[idx], nil
 }
 
+// GetAsString returns value at idx.
+func (c *ColumnVarChar) GetAsString(idx int) (string, error) {
+	if idx < 0 || idx > c.Len() {
+		return "", errors.New("index out of range")
+	}
+	return c.values[idx], nil
+}
+
 // FieldData return column data mapped to schema.FieldData
 func (c *ColumnVarChar) FieldData() *schema.FieldData {
 	fd := &schema.FieldData{
diff --git a/entity/columns_vector_gen.go b/entity/columns_vector_gen.go
index daa2ff5..048158c 100755
--- a/entity/columns_vector_gen.go
+++ b/entity/columns_vector_gen.go
@@ -13,6 +13,7 @@ import (
 
 // ColumnBinaryVector generated columns type for BinaryVector
 type ColumnBinaryVector struct {
+	ColumnBase
 	name   string
 	dim    int
 	values [][]byte
@@ -99,6 +100,7 @@ func NewColumnBinaryVector(name string, dim int, values [][]byte) *ColumnBinaryV
 
 // ColumnFloatVector generated columns type for FloatVector
 type ColumnFloatVector struct {
+	ColumnBase
 	name   string
 	dim    int
 	values [][]float32
diff --git a/entity/gen/gen.go b/entity/gen/gen.go
index 2478dc8..68510f5 100644
--- a/entity/gen/gen.go
+++ b/entity/gen/gen.go
@@ -37,6 +37,7 @@ import (
 {{ range .Types }}{{with .}}
 // Column{{.TypeName}} generated columns type for {{.TypeName}}
 type Column{{.TypeName}} struct {
+	ColumnBase
 	name   string
 	values []{{.TypeDef}}
 }
@@ -137,6 +138,7 @@ import (
 {{ range .Types }}{{with.}}
 // Column{{.TypeName}} generated columns type for {{.TypeName}}
 type Column{{.TypeName}} struct {
+	ColumnBase
 	name   string
 	dim    int
 	values []{{.TypeDef}}
diff --git a/examples/dynamic_schema/dynamic_schema.go b/examples/dynamic_schema/dynamic_schema.go
index 667fedb..0d090c7 100644
--- a/examples/dynamic_schema/dynamic_schema.go
+++ b/examples/dynamic_schema/dynamic_schema.go
@@ -134,13 +134,13 @@ func main() {
 		})
 	}
 
-	fmt.Printf(msgFmt, "start to insert by rows")
 	_, err = c.InsertByRows(ctx, collectionName, "", rows)
 	if err != nil {
 		log.Fatal("failed to insert by rows: ", err.Error())
 	}
 
 	// insert by map[string]interface{}
+	fmt.Printf(msgFmt, "start to inserting by MapRow")
 	m := make(map[string]interface{})
 	m["ID"] = int64(nEntities)
 	vec := make([]float32, 0, dim)
@@ -186,7 +186,7 @@ func main() {
 	}
 	begin := time.Now()
 	sp, _ := entity.NewIndexIvfFlatSearchParam(16)
-	sRet, err := c.Search(ctx, collectionName, nil, "", []string{ /*randomCol, typeCol*/ "*"}, vec2search,
+	sRet, err := c.Search(ctx, collectionName, nil, "", []string{randomCol, typeCol}, vec2search,
 		embeddingCol, entity.L2, topK, sp)
 	end := time.Now()
 	if err != nil {
@@ -195,7 +195,7 @@ func main() {
 
 	fmt.Println("results:")
 	for _, res := range sRet {
-		printResult(&res)
+		printResult(&res, map[string]string{randomCol: "double", typeCol: "int"})
 	}
 	fmt.Printf("\tsearch latency: %dms\n", end.Sub(begin)/time.Millisecond)
 
@@ -210,7 +210,7 @@ func main() {
 	}
 	fmt.Println("results:")
 	for _, res := range sRet2 {
-		printResult(&res)
+		printResult(&res, map[string]string{randomCol: "double", typeCol: "int"})
 	}
 	fmt.Printf("\tsearch latency: %dms\n", end.Sub(begin)/time.Millisecond)
 
@@ -221,7 +221,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("failed to query result, err: %v", err)
 	}
-	printResultSet(sRet3)
+	printResultSet(sRet3, map[string]string{idCol: "int", randomCol: "double", typeCol: "int"})
 
 	// $meta["source"]
 	expr = "source in [1] and random > 0.1"
@@ -230,7 +230,7 @@ func main() {
 	if err != nil {
 		log.Fatalf("failed to query result, err: %v", err)
 	}
-	printResultSet(sRet3)
+	printResultSet(sRet3, map[string]string{idCol: "int", randomCol: "double", typeCol: "int", sourceCol: "int"})
 
 	// drop collection
 	fmt.Printf(msgFmt, "drop collection `dynamic_example`")
@@ -239,47 +239,50 @@ func main() {
 	}
 }
 
-func printResultSet(sRets []entity.Column) {
-	for _, field := range sRets {
-		fmt.Println(field.Name(), ":")
-		if dc, ok := field.(*entity.ColumnDynamic); ok {
-			for i := 0; i < field.Len(); i++ {
-				switch dc.Name() {
-				case typeCol, sourceCol:
-					v, err := dc.GetInt64(i)
-					if err != nil {
-						fmt.Println(err.Error())
-						continue
-					}
-					fmt.Print(v)
-				case randomCol:
-					v, err := dc.GetDouble(i)
-					if err != nil {
-						fmt.Println(err.Error())
-						continue
-					}
-					fmt.Print(v)
-				default:
-					continue
+func printResultSet(sRets client.ResultSet, outputInfo map[string]string) {
+	for name, typ := range outputInfo {
+		column := sRets.GetColumn(name)
+		if column == nil {
+			fmt.Printf("column %s not found in result set\n", name)
+			continue
+		}
+
+		fmt.Printf("Result Column %s, count: %d\n", name, column.Len())
+		switch typ {
+		case "int":
+			var data []int64
+			for i := 0; i < column.Len(); i++ {
+				line, err := column.GetAsInt64(i)
+				if err != nil {
+					fmt.Printf("failed to get column %s at index %d, err: %s\n", name, i, err.Error())
 				}
-				if i != field.Len()-1 {
-					fmt.Print(", ")
+				data = append(data, line)
+			}
+			fmt.Println("Data:", data)
+		case "string":
+			var data []string
+			for i := 0; i < column.Len(); i++ {
+				line, err := column.GetAsString(i)
+				if err != nil {
+					fmt.Printf("failed to get column %s at index %d, err: %s\n", name, i, err.Error())
 				}
+				data = append(data, line)
 			}
-			fmt.Println()
-			continue
-		}
-		for i := 0; i < field.Len(); i++ {
-			v, _ := field.Get(i)
-			fmt.Print(v)
-			if i != field.Len()-1 {
-				fmt.Print(", ")
+			fmt.Println("Data:", data)
+		case "double":
+			var data []float64
+			for i := 0; i < column.Len(); i++ {
+				line, err := column.GetAsDouble(i)
+				if err != nil {
+					fmt.Printf("failed to get column %s at index %d, err: %s\n", name, i, err.Error())
+				}
+				data = append(data, line)
 			}
+			fmt.Println("Data:", data)
 		}
-		fmt.Println()
 	}
 }
 
-func printResult(sRet *client.SearchResult) {
-	printResultSet(sRet.Fields)
+func printResult(sRet *client.SearchResult, outputInfo map[string]string) {
+	printResultSet(sRet.Fields, outputInfo)
 }


Test patch:
diff --git a/client/client_mock_test.go b/client/client_mock_test.go
index 84cdd39..28f7472 100644
--- a/client/client_mock_test.go
+++ b/client/client_mock_test.go
@@ -18,6 +18,7 @@ import (
 	"github.com/stretchr/testify/mock"
 	"github.com/stretchr/testify/suite"
 	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials/insecure"
 	"google.golang.org/grpc/test/bufconn"
 )
 
@@ -60,8 +61,8 @@ func (s *MockSuiteBase) mockDialer(context.Context, string) (net.Conn, error) {
 func (s *MockSuiteBase) SetupTest() {
 	c, err := NewGrpcClient(context.Background(), "bufnet2",
 		grpc.WithBlock(),
-		grpc.WithInsecure(),
 		grpc.WithContextDialer(s.mockDialer),
+		grpc.WithTransportCredentials(insecure.NewCredentials()),
 	)
 	s.Require().NoError(err)
 	s.setupConnect()
diff --git a/client/data_test.go b/client/data_test.go
index f986fa3..ce6a154 100644
--- a/client/data_test.go
+++ b/client/data_test.go
@@ -453,7 +453,7 @@ func (s *SearchSuite) TestSearchSuccess() {
 		s.Require().NotNil(columnA)
 		column, ok := columnA.(*entity.ColumnDynamic)
 		s.Require().True(ok)
-		v, err := column.GetInt64(0)
+		v, err := column.GetAsInt64(0)
 		s.NoError(err)
 		s.Equal(int64(123), v)
 
@@ -461,7 +461,7 @@ func (s *SearchSuite) TestSearchSuccess() {
 		s.Require().NotNil(columnB)
 		column, ok = columnB.(*entity.ColumnDynamic)
 		s.Require().True(ok)
-		str, err := column.GetString(1)
+		str, err := column.GetAsString(1)
 		s.NoError(err)
 		s.Equal("abc", str)
 	})
@@ -686,7 +686,7 @@ func (s *QuerySuite) TestQuerySuccess() {
 		columnA := rs.GetColumn("A").(*entity.ColumnDynamic)
 		s.Require().True(ok)
 		s.Require().NotNil(columnA)
-		v, err = columnA.GetInt64(0)
+		v, err = columnA.GetAsInt64(0)
 		s.NoError(err)
 		s.Equal(int64(123), v)
 	})
diff --git a/client/resource_group_test.go b/client/resource_group_test.go
index bf2ac01..78bc182 100644
--- a/client/resource_group_test.go
+++ b/client/resource_group_test.go
@@ -53,11 +53,6 @@ func (s *ResourceGroupSuite) TestListResourceGroups() {
 	s.Run("request_fails", func() {
 		defer s.resetMock()
 
-		rgs := make([]string, 0, 5)
-		for i := 0; i < 5; i++ {
-			rgs = append(rgs, randStr(10))
-		}
-
 		s.mock.EXPECT().ListResourceGroups(mock.Anything, mock.AnythingOfType("*milvuspb.ListResourceGroupsRequest")).
 			Return(nil, errors.New("mocked grpc error"))
 
@@ -68,11 +63,6 @@ func (s *ResourceGroupSuite) TestListResourceGroups() {
 	s.Run("server_return_err", func() {
 		defer s.resetMock()
 
-		rgs := make([]string, 0, 5)
-		for i := 0; i < 5; i++ {
-			rgs = append(rgs, randStr(10))
-		}
-
 		s.mock.EXPECT().ListResourceGroups(mock.Anything, mock.AnythingOfType("*milvuspb.ListResourceGroupsRequest")).
 			Return(&server.ListResourceGroupsResponse{Status: &common.Status{ErrorCode: common.ErrorCode_UnexpectedError}}, nil)
 
@@ -158,11 +148,6 @@ func (s *ResourceGroupSuite) TestDescribeResourceGroup() {
 			outgoingNum[fmt.Sprintf("coll_%s", randStr(6))] = rand.Int31n(5) + 1
 		}
 
-		type testColl struct {
-			Name      string
-			Capacity  int32
-			Available int32
-		}
 		s.mock.EXPECT().DescribeResourceGroup(mock.Anything, mock.AnythingOfType("*milvuspb.DescribeResourceGroupRequest")).
 			Run(func(_ context.Context, req *server.DescribeResourceGroupRequest) {
 				s.Equal(rgName, req.GetResourceGroup())
@@ -196,10 +181,6 @@ func (s *ResourceGroupSuite) TestDescribeResourceGroup() {
 		defer s.resetMock()
 
 		rgName := randStr(10)
-		rgs := make([]string, 0, 5)
-		for i := 0; i < 5; i++ {
-			rgs = append(rgs, randStr(10))
-		}
 
 		s.mock.EXPECT().DescribeResourceGroup(mock.Anything, mock.AnythingOfType("*milvuspb.DescribeResourceGroupRequest")).
 			Run(func(_ context.Context, req *server.DescribeResourceGroupRequest) {
@@ -215,10 +196,6 @@ func (s *ResourceGroupSuite) TestDescribeResourceGroup() {
 		defer s.resetMock()
 
 		rgName := randStr(10)
-		rgs := make([]string, 0, 5)
-		for i := 0; i < 5; i++ {
-			rgs = append(rgs, randStr(10))
-		}
 
 		s.mock.EXPECT().DescribeResourceGroup(mock.Anything, mock.AnythingOfType("*milvuspb.DescribeResourceGroupRequest")).
 			Run(func(_ context.Context, req *server.DescribeResourceGroupRequest) {
@@ -292,11 +269,6 @@ func (s *ResourceGroupSuite) TestTransferNodes() {
 		targetRg := randStr(10)
 		nodeNum := rand.Int31n(5) + 1
 
-		rgs := make([]string, 0, 5)
-		for i := 0; i < 5; i++ {
-			rgs = append(rgs, randStr(10))
-		}
-
 		s.mock.EXPECT().TransferNode(mock.Anything, mock.AnythingOfType("*milvuspb.TransferNodeRequest")).
 			Run(func(_ context.Context, req *server.TransferNodeRequest) {
 				s.Equal(sourceRg, req.GetSourceResourceGroup())
@@ -360,11 +332,6 @@ func (s *ResourceGroupSuite) TestTransferReplica() {
 		targetRg := randStr(10)
 		replicaNum := rand.Int63n(5) + 1
 
-		rgs := make([]string, 0, 5)
-		for i := 0; i < 5; i++ {
-			rgs = append(rgs, randStr(10))
-		}
-
 		s.mock.EXPECT().TransferReplica(mock.Anything, mock.AnythingOfType("*milvuspb.TransferReplicaRequest")).
 			Run(func(_ context.Context, req *server.TransferReplicaRequest) {
 				s.Equal(sourceRg, req.GetSourceResourceGroup())
diff --git a/entity/columns_dynamic_test.go b/entity/columns_dynamic_test.go
index 017b665..f7a081b 100644
--- a/entity/columns_dynamic_test.go
+++ b/entity/columns_dynamic_test.go
@@ -27,7 +27,7 @@ func (s *ColumnDynamicSuite) TestGetInt() {
 			column := NewColumnDynamic(&ColumnJSONBytes{
 				values: [][]byte{[]byte(c.input)},
 			}, "field")
-			v, err := column.GetInt64(0)
+			v, err := column.GetAsInt64(0)
 			if c.expectErr {
 				s.Error(err)
 				return
@@ -55,7 +55,7 @@ func (s *ColumnDynamicSuite) TestGetString() {
 			column := NewColumnDynamic(&ColumnJSONBytes{
 				values: [][]byte{[]byte(c.input)},
 			}, "field")
-			v, err := column.GetString(0)
+			v, err := column.GetAsString(0)
 			if c.expectErr {
 				s.Error(err)
 				return
@@ -83,7 +83,7 @@ func (s *ColumnDynamicSuite) TestGetBool() {
 			column := NewColumnDynamic(&ColumnJSONBytes{
 				values: [][]byte{[]byte(c.input)},
 			}, "field")
-			v, err := column.GetBool(0)
+			v, err := column.GetAsBool(0)
 			if c.expectErr {
 				s.Error(err)
 				return
@@ -111,7 +111,7 @@ func (s *ColumnDynamicSuite) TestGetDouble() {
 			column := NewColumnDynamic(&ColumnJSONBytes{
 				values: [][]byte{[]byte(c.input)},
 			}, "field")
-			v, err := column.GetDouble(0)
+			v, err := column.GetAsDouble(0)
 			if c.expectErr {
 				s.Error(err)
 				return
@@ -129,16 +129,16 @@ func (s *ColumnDynamicSuite) TestIndexOutOfRange() {
 
 	s.Equal("field", column.Name())
 
-	_, err = column.GetInt64(0)
+	_, err = column.GetAsInt64(0)
 	s.Error(err)
 
-	_, err = column.GetString(0)
+	_, err = column.GetAsString(0)
 	s.Error(err)
 
-	_, err = column.GetBool(0)
+	_, err = column.GetAsBool(0)
 	s.Error(err)
 
-	_, err = column.GetDouble(0)
+	_, err = column.GetAsDouble(0)
 	s.Error(err)
 }