Repository: milvus-io/milvus-sdk-go
Pull request #578 (2023-09-06 07:39:31)

add delete by expression method
relate: https://github.com/milvus-io/milvus-sdk-go/issues/577

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

This pull-request has been approved by: *<a href="https://github.com/milvus-io/milvus-sdk-go/pull/578#" title="Author self-approved">aoiasd</a>*
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **sunby** after the PR has been reviewed.
You can assign the PR to them by writing `/assign @sunby` in a comment when ready.

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).

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

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

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":["sunby"]} -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/578?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) Report
> Merging [#578](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/578?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) (3fba8a0) into [master](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/commit/684ef2dc3378c70eb75d6331e35b4978978595aa?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io) (684ef2d) will **increase** coverage by `0.05%`.
> The diff coverage is `91.66%`.

[![Impacted file tree graph](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/578/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/578?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     #578      +/-   ##
==========================================
+ Coverage   82.79%   82.84%   +0.05%     
==========================================
  Files          40       40              
  Lines        3626     3650      +24     
==========================================
+ Hits         3002     3024      +22     
- Misses        511      512       +1     
- Partials      113      114       +1     
```


| [Files Changed](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/578?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/578?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2NsaWVudC5nbw==) | `28.94% <ø> (ø)` | |
| [client/insert.go](https://app.codecov.io/gh/milvus-io/milvus-sdk-go/pull/578?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=milvus-io#diff-Y2xpZW50L2luc2VydC5nbw==) | `80.51% <91.66%> (+0.94%)` | :arrow_up: |


Patch:
diff --git a/README.md b/README.md
index 6928418..2bae6fd 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Go SDK for [Milvus](https://github.com/milvus-io/milvus). To contribute code to
 |Milvus version| Recommended Go SDK version |
 |:-----:|:-----:|
 | 2.3.x | [2.3.0](https://github.com/milvus-io/milvus-sdk-go/tree/v2.3.0) |
-| 2.2.x | [2.2.7](https://github.com/milvus-io/milvus-sdk-go/tree/v2.2.7) |
+| 2.2.x | [2.2.8](https://github.com/milvus-io/milvus-sdk-go/tree/v2.2.8) |
 | 2.1.0 | [2.1.0](https://github.com/milvus-io/milvus-sdk-go/tree/v2.1.0) |
 | 2.0.0 | [2.0.0](https://github.com/milvus-io/milvus-sdk-go/tree/v2.0.0) |
 | 1.1.x | [1.1.0](https://github.com/milvus-io/milvus-sdk-go/tree/v1.1.0) |
diff --git a/client/client.go b/client/client.go
index 5f3cd73..dda234d 100644
--- a/client/client.go
+++ b/client/client.go
@@ -130,6 +130,8 @@ type Client interface {
 	FlushV2(ctx context.Context, collName string, async bool) ([]int64, []int64, int64, error)
 	// DeleteByPks deletes entries related to provided primary keys
 	DeleteByPks(ctx context.Context, collName string, partitionName string, ids entity.Column) error
+	// Delete deletes entries match expression
+	Delete(ctx context.Context, collName string, partitionName string, expr string) error
 	// Upsert column-based data of collection, returns id column values
 	Upsert(ctx context.Context, collName string, partitionName string, columns ...entity.Column) (entity.Column, error)
 	// Search search with bool expression
diff --git a/client/insert.go b/client/insert.go
index 24fb682..43ccfb8 100644
--- a/client/insert.go
+++ b/client/insert.go
@@ -299,6 +299,44 @@ func (c *GrpcClient) DeleteByPks(ctx context.Context, collName string, partition
 	return nil
 }
 
+// Delete deletes entries match expression
+func (c *GrpcClient) Delete(ctx context.Context, collName string, partitionName string, expr string) error {
+	if c.Service == nil {
+		return ErrClientNotReady
+	}
+
+	// check collection name
+	if err := c.checkCollectionExists(ctx, collName); err != nil {
+		return err
+	}
+
+	// check partition name
+	if partitionName != "" {
+		err := c.checkPartitionExists(ctx, collName, partitionName)
+		if err != nil {
+			return err
+		}
+	}
+
+	req := &milvuspb.DeleteRequest{
+		DbName:         "",
+		CollectionName: collName,
+		PartitionName:  partitionName,
+		Expr:           expr,
+	}
+
+	resp, err := c.Service.Delete(ctx, req)
+	if err != nil {
+		return err
+	}
+	err = handleRespStatus(resp.GetStatus())
+	if err != nil {
+		return err
+	}
+	MetaCache.setSessionTs(collName, resp.Timestamp)
+	return nil
+}
+
 // Upsert Index into collection with column-based format
 // collName is the collection name
 // partitionName is the partition to upsert, if not specified(empty), default partition will be used


Test patch:
diff --git a/client/data_test.go b/client/data_test.go
index e580ee9..0e787b6 100644
--- a/client/data_test.go
+++ b/client/data_test.go
@@ -267,6 +267,72 @@ func TestGrpcDeleteByPks(t *testing.T) {
 	})
 }
 
+func TestGrpcDelete(t *testing.T) {
+	ctx := context.Background()
+
+	c := testClient(ctx, t)
+	defer c.Close()
+
+	mockServer.SetInjection(MDescribeCollection, describeCollectionInjection(t, 1, testCollectionName, defaultSchema()))
+	defer mockServer.DelInjection(MDescribeCollection)
+
+	t.Run("normal delete by pks", func(t *testing.T) {
+		partName := "testPart"
+		mockServer.SetInjection(MHasPartition, hasPartitionInjection(t, testCollectionName, true, partName))
+		defer mockServer.DelInjection(MHasPartition)
+		mockServer.SetInjection(MDelete, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			req, ok := raw.(*milvuspb.DeleteRequest)
+			if !ok {
+				t.FailNow()
+			}
+			assert.Equal(t, testCollectionName, req.GetCollectionName())
+			assert.Equal(t, partName, req.GetPartitionName())
+
+			resp := &milvuspb.MutationResult{}
+			s, err := SuccessStatus()
+			resp.Status = s
+			return resp, err
+		})
+		defer mockServer.DelInjection(MDelete)
+
+		err := c.Delete(ctx, testCollectionName, partName, "")
+		assert.NoError(t, err)
+	})
+
+	t.Run("Bad request deletes", func(t *testing.T) {
+		partName := "testPart"
+		mockServer.SetInjection(MHasPartition, hasPartitionInjection(t, testCollectionName, false, partName))
+		defer mockServer.DelInjection(MHasPartition)
+
+		// non-exist collection
+		err := c.Delete(ctx, "non-exists-collection", "", "")
+		assert.Error(t, err)
+
+		// non-exist parition
+		err = c.Delete(ctx, testCollectionName, "non-exists-part", "")
+		assert.Error(t, err)
+	})
+	t.Run("delete services fail", func(t *testing.T) {
+		mockServer.SetInjection(MDelete, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			resp := &milvuspb.MutationResult{}
+			return resp, errors.New("mockServer.d error")
+		})
+
+		err := c.Delete(ctx, testCollectionName, "", "")
+		assert.Error(t, err)
+
+		mockServer.SetInjection(MDelete, func(_ context.Context, raw proto.Message) (proto.Message, error) {
+			resp := &milvuspb.MutationResult{}
+			resp.Status = &commonpb.Status{
+				ErrorCode: commonpb.ErrorCode_UnexpectedError,
+			}
+			return resp, nil
+		})
+		err = c.Delete(ctx, testCollectionName, "", "")
+		assert.Error(t, err)
+	})
+}
+
 type SearchSuite struct {
 	MockSuiteBase
 	sch        *entity.Schema
diff --git a/test/base/milvus_client.go b/test/base/milvus_client.go
index 61da33c..39921a5 100644
--- a/test/base/milvus_client.go
+++ b/test/base/milvus_client.go
@@ -382,6 +382,14 @@ func (mc *MilvusClient) DeleteByPks(ctx context.Context, collName string, partit
 	return err
 }
 
+// Delete deletes entries match expression
+func (mc *MilvusClient) Delete(ctx context.Context, collName string, partitionName string, expr string) error {
+	preRequest("DeleteByPks", ctx, collName, partitionName, expr)
+	err := mc.mClient.Delete(ctx, collName, partitionName, expr)
+	postResponse("DeleteByPks", err)
+	return err
+}
+
 // Search search from collection
 func (mc *MilvusClient) 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 ...client.SearchQueryOptionFunc,