github.com/milvus-io/milvus-sdk-go/v2@v2.4.1/test/testcases/delete_test.go (about)

     1  //go:build L0
     2  
     3  package testcases
     4  
     5  import (
     6  	"fmt"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/milvus-io/milvus-sdk-go/v2/client"
    11  
    12  	"github.com/milvus-io/milvus-sdk-go/v2/entity"
    13  	"github.com/milvus-io/milvus-sdk-go/v2/test/common"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  // test delete int64 pks
    18  func TestDelete(t *testing.T) {
    19  	ctx := createContext(t, time.Second*common.DefaultTimeout)
    20  	// connect
    21  	mc := createMilvusClient(ctx, t)
    22  
    23  	// create, insert, index
    24  	collName, ids := createCollectionWithDataIndex(ctx, t, mc, true, true, client.WithConsistencyLevel(entity.ClStrong))
    25  
    26  	// Load collection
    27  	errLoad := mc.LoadCollection(ctx, collName, false)
    28  	common.CheckErr(t, errLoad, true)
    29  
    30  	// delete
    31  	deleteIds := ids.Slice(0, 10)
    32  	errDelete := mc.DeleteByPks(ctx, collName, common.DefaultPartition, deleteIds)
    33  	common.CheckErr(t, errDelete, true)
    34  
    35  	// query, verify delete success
    36  	queryRes, errQuery := mc.QueryByPks(ctx, collName, []string{common.DefaultPartition}, deleteIds, []string{})
    37  	common.CheckErr(t, errQuery, true)
    38  	require.Zero(t, queryRes[0].Len())
    39  }
    40  
    41  // test delete with string pks
    42  func TestDeleteStringPks(t *testing.T) {
    43  	ctx := createContext(t, time.Second*common.DefaultTimeout)
    44  	// connect
    45  	mc := createMilvusClient(ctx, t)
    46  
    47  	// create, insert, index
    48  	collName, ids := createVarcharCollectionWithDataIndex(ctx, t, mc, true, client.WithConsistencyLevel(entity.ClStrong))
    49  
    50  	// delete
    51  	deleteIds := ids.Slice(0, 10)
    52  	errDelete := mc.DeleteByPks(ctx, collName, common.DefaultPartition, deleteIds)
    53  	common.CheckErr(t, errDelete, true)
    54  
    55  	// Load collection
    56  	errLoad := mc.LoadCollection(ctx, collName, false)
    57  	common.CheckErr(t, errLoad, true)
    58  
    59  	// query, verify delete success
    60  	queryRes, errQuery := mc.QueryByPks(ctx, collName, []string{common.DefaultPartition}, deleteIds, []string{})
    61  	common.CheckErr(t, errQuery, true)
    62  	require.Zero(t, queryRes[0].Len())
    63  }
    64  
    65  // test delete from empty collection
    66  func TestDeleteEmptyCollection(t *testing.T) {
    67  	ctx := createContext(t, time.Second*common.DefaultTimeout)
    68  	// connect
    69  	mc := createMilvusClient(ctx, t)
    70  
    71  	// create
    72  	collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards)
    73  
    74  	// delete
    75  	deleteIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0})
    76  	errDelete := mc.DeleteByPks(ctx, collName, common.DefaultPartition, deleteIds)
    77  	common.CheckErr(t, errDelete, true)
    78  }
    79  
    80  // test delete from an not exist collection
    81  func TestDeleteNotExistCollection(t *testing.T) {
    82  	ctx := createContext(t, time.Second*common.DefaultTimeout)
    83  	// connect
    84  	mc := createMilvusClient(ctx, t)
    85  
    86  	// flush and check row count
    87  	deleteIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0, 1})
    88  	errDelete := mc.DeleteByPks(ctx, "collName", common.DefaultPartition, deleteIds)
    89  	common.CheckErr(t, errDelete, false, "collection collName does not exist")
    90  }
    91  
    92  // test delete from an not exist partition
    93  func TestDeleteNotExistPartition(t *testing.T) {
    94  	ctx := createContext(t, time.Second*common.DefaultTimeout)
    95  	// connect
    96  	mc := createMilvusClient(ctx, t)
    97  
    98  	// create, insert, index
    99  	collName, ids := createCollectionWithDataIndex(ctx, t, mc, true, true)
   100  
   101  	// Load collection
   102  	errLoad := mc.LoadCollection(ctx, collName, false)
   103  	common.CheckErr(t, errLoad, true)
   104  
   105  	// delete
   106  	deleteIds := ids.Slice(0, 10)
   107  	errDelete := mc.DeleteByPks(ctx, collName, "p1", deleteIds)
   108  	common.CheckErr(t, errDelete, false, fmt.Sprintf("partition p1 of collection %s does not exist", collName))
   109  }
   110  
   111  // test delete empty partition names
   112  func TestDeleteEmptyPartitionNames(t *testing.T) {
   113  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   114  	// connect
   115  	mc := createMilvusClient(ctx, t)
   116  
   117  	emptyPartitionName := ""
   118  	// create
   119  	collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards, client.WithConsistencyLevel(entity.ClStrong))
   120  
   121  	// insert "" partition and flush
   122  	intColumn, floatColumn, vecColumn := common.GenDefaultColumnData(0, common.DefaultNb, common.DefaultDim)
   123  	_, errInsert := mc.Insert(ctx, collName, emptyPartitionName, intColumn, floatColumn, vecColumn)
   124  	common.CheckErr(t, errInsert, true)
   125  	mc.Flush(ctx, collName, false)
   126  
   127  	// delete
   128  	deleteIds := intColumn.Slice(0, 10)
   129  	errDelete := mc.DeleteByPks(ctx, collName, emptyPartitionName, deleteIds)
   130  	common.CheckErr(t, errDelete, true)
   131  
   132  	// create index
   133  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   134  	mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false, client.WithIndexName(""))
   135  
   136  	// Load collection
   137  	errLoad := mc.LoadCollection(ctx, collName, false)
   138  	common.CheckErr(t, errLoad, true)
   139  
   140  	// query, verify delete success
   141  	queryRes, errQuery := mc.QueryByPks(ctx, collName, []string{common.DefaultPartition}, deleteIds, []string{})
   142  	common.CheckErr(t, errQuery, true)
   143  	require.Zero(t, queryRes[0].Len())
   144  }
   145  
   146  // test delete from empty partition
   147  func TestDeleteEmptyPartition(t *testing.T) {
   148  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   149  	// connect
   150  	mc := createMilvusClient(ctx, t)
   151  
   152  	// create, insert into default partition, index
   153  	collName, ids := createCollectionWithDataIndex(ctx, t, mc, true, true)
   154  
   155  	// create partition and empty
   156  	mc.CreatePartition(ctx, collName, "p1")
   157  
   158  	// Load collection
   159  	errLoad := mc.LoadCollection(ctx, collName, false)
   160  	common.CheckErr(t, errLoad, true)
   161  
   162  	// delete from empty partition p1
   163  	deleteIds := ids.Slice(0, 10)
   164  	errDelete := mc.DeleteByPks(ctx, collName, "p1", deleteIds)
   165  	common.CheckErr(t, errDelete, true)
   166  
   167  	// query deleteIds in default partition
   168  	queryResult, _ := mc.QueryByPks(
   169  		ctx,
   170  		collName,
   171  		[]string{},
   172  		deleteIds,
   173  		[]string{common.DefaultIntFieldName},
   174  	)
   175  	common.CheckQueryResult(t, queryResult, []entity.Column{deleteIds})
   176  }
   177  
   178  // test delete from partition which data not meet ids
   179  func TestDeletePartitionIdsNotMatch(t *testing.T) {
   180  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   181  	// connect
   182  	mc := createMilvusClient(ctx, t)
   183  
   184  	// create collection and insert [0, nb) into default partition, [nb, nb*2) into new partition
   185  	collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards)
   186  	partitionName, vecColumnDefault, _ := createInsertTwoPartitions(ctx, t, mc, collName, common.DefaultNb)
   187  
   188  	// delete [0:10) from new partition -> delete nothing
   189  	deleteIds := vecColumnDefault.IdsColumn.Slice(0, 10)
   190  	errDelete := mc.DeleteByPks(ctx, collName, partitionName, deleteIds)
   191  	common.CheckErr(t, errDelete, true)
   192  
   193  	// create index
   194  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   195  	mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
   196  
   197  	// Load collection
   198  	errLoad := mc.LoadCollection(ctx, collName, false)
   199  	common.CheckErr(t, errLoad, true)
   200  
   201  	// query deleteIds in default partition
   202  	queryResult, _ := mc.QueryByPks(
   203  		ctx,
   204  		collName,
   205  		[]string{common.DefaultPartition},
   206  		deleteIds,
   207  		[]string{common.DefaultIntFieldName},
   208  	)
   209  	common.CheckQueryResult(t, queryResult, []entity.Column{deleteIds})
   210  }
   211  
   212  // test delete with nil ids
   213  func TestDeleteEmptyIds(t *testing.T) {
   214  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   215  	// connect
   216  	mc := createMilvusClient(ctx, t)
   217  
   218  	// create
   219  	collName := createDefaultCollection(ctx, t, mc, false, common.DefaultShards)
   220  
   221  	// delete
   222  	errDelete := mc.DeleteByPks(ctx, collName, common.DefaultPartition, entity.NewColumnInt64(common.DefaultIntFieldName, []int64{}))
   223  	common.CheckErr(t, errDelete, false, "ids len must not be zero")
   224  }
   225  
   226  // test delete ids field not pk int64
   227  func TestDeleteNotPkIds(t *testing.T) {
   228  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   229  	// connect
   230  	mc := createMilvusClient(ctx, t)
   231  
   232  	// create, insert, index
   233  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true)
   234  
   235  	// Load collection
   236  	errLoad := mc.LoadCollection(ctx, collName, false)
   237  	common.CheckErr(t, errLoad, true)
   238  
   239  	// delete
   240  	deleteIds := entity.NewColumnFloat(common.DefaultFloatFieldName, []float32{0})
   241  	errDelete := mc.DeleteByPks(ctx, collName, common.DefaultPartition, deleteIds)
   242  	common.CheckErr(t, errDelete, false, "only int64 and varchar column can be primary key for now")
   243  }
   244  
   245  // test delete with duplicated data ids
   246  func TestDeleteDuplicatedPks(t *testing.T) {
   247  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   248  	// connect
   249  	mc := createMilvusClient(ctx, t)
   250  
   251  	// create, insert, index
   252  	collName, _ := createCollectionWithDataIndex(ctx, t, mc, true, true, client.WithConsistencyLevel(entity.ClStrong))
   253  
   254  	// Load collection
   255  	errLoad := mc.LoadCollection(ctx, collName, false)
   256  	common.CheckErr(t, errLoad, true)
   257  
   258  	// delete
   259  	deleteIds := entity.NewColumnInt64(common.DefaultIntFieldName, []int64{0, 0, 0, 0, 0})
   260  	errDelete := mc.DeleteByPks(ctx, collName, common.DefaultPartition, deleteIds)
   261  	common.CheckErr(t, errDelete, true)
   262  
   263  	// query, verify delete success
   264  	queryRes, errQuery := mc.QueryByPks(ctx, collName, []string{common.DefaultPartition}, deleteIds, []string{})
   265  	common.CheckErr(t, errQuery, true)
   266  	require.Zero(t, queryRes[0].Len())
   267  }
   268  
   269  func TestDeleteExpressions(t *testing.T) {
   270  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   271  	// connect
   272  	mc := createMilvusClient(ctx, t)
   273  
   274  	// create collection
   275  	cp := CollectionParams{
   276  		CollectionFieldsType: AllFields,
   277  		AutoID:               false,
   278  		EnableDynamicField:   true,
   279  		ShardsNum:            common.DefaultShards,
   280  		Dim:                  common.DefaultDim,
   281  	}
   282  	collName := createCollection(ctx, t, mc, cp, client.WithConsistencyLevel(entity.ClStrong))
   283  
   284  	// insert
   285  	dp := DataParams{
   286  		CollectionName:       collName,
   287  		PartitionName:        "",
   288  		CollectionFieldsType: AllFields,
   289  		start:                0,
   290  		nb:                   common.DefaultNb,
   291  		dim:                  common.DefaultDim,
   292  		EnableDynamicField:   true,
   293  	}
   294  	_, _ = insertData(ctx, t, mc, dp)
   295  
   296  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   297  	for _, field := range common.AllFloatVectorsFieldNames {
   298  		err := mc.CreateIndex(ctx, collName, field, idx, false)
   299  		common.CheckErr(t, err, true)
   300  	}
   301  
   302  	flatIdx, _ := entity.NewIndexBinFlat(entity.JACCARD, 16)
   303  
   304  	err := mc.CreateIndex(ctx, collName, common.DefaultBinaryVecFieldName, flatIdx, false)
   305  	common.CheckErr(t, err, true)
   306  
   307  	// Load collection
   308  	errLoad := mc.LoadCollection(ctx, collName, false)
   309  	common.CheckErr(t, errLoad, true)
   310  
   311  	// query with different expr and count
   312  	exprCounts := []string{
   313  		// pk int64 field expr: < in && ||
   314  		fmt.Sprintf("%s < 1000", common.DefaultIntFieldName),
   315  		fmt.Sprintf("%s in [0, 1, 2]", common.DefaultIntFieldName),
   316  		fmt.Sprintf("%s >= 1000 && %s < 2000", common.DefaultIntFieldName, common.DefaultIntFieldName),
   317  		fmt.Sprintf("%s >= 1000 || %s > 2000", common.DefaultIntFieldName, common.DefaultIntFieldName),
   318  		fmt.Sprintf("%s < 1000", common.DefaultFloatFieldName),
   319  
   320  		// json and dynamic field filter expr: == < in bool/ list/ int
   321  		fmt.Sprintf("%s['number'] == 0", common.DefaultJSONFieldName),
   322  		fmt.Sprintf("%s['number'] < 100 and %s['number'] != 0", common.DefaultJSONFieldName, common.DefaultJSONFieldName),
   323  		fmt.Sprintf("%s < 100", common.DefaultDynamicNumberField),
   324  		"dynamicNumber % 2 == 0",
   325  		fmt.Sprintf("%s['bool'] == true", common.DefaultJSONFieldName),
   326  		fmt.Sprintf("%s == false", common.DefaultDynamicBoolField),
   327  		fmt.Sprintf("%s in ['1', '2'] ", common.DefaultDynamicStringField),
   328  		fmt.Sprintf("%s['string'] in ['1', '2', '5'] ", common.DefaultJSONFieldName),
   329  		fmt.Sprintf("%s['list'] == [1, 2] ", common.DefaultJSONFieldName),
   330  		fmt.Sprintf("%s['list'] == [0, 1] ", common.DefaultJSONFieldName),
   331  		fmt.Sprintf("%s['list'][0] < 10 ", common.DefaultJSONFieldName),
   332  		fmt.Sprintf("%s[\"dynamicList\"] != [2, 3]", common.DefaultDynamicFieldName),
   333  		fmt.Sprintf("%s > 2500", common.DefaultJSONFieldName),
   334  		fmt.Sprintf("%s > 2000.5", common.DefaultJSONFieldName),
   335  		fmt.Sprintf("%s[0] == 2503", common.DefaultJSONFieldName),
   336  		fmt.Sprintf("%s like '21%%' ", common.DefaultJSONFieldName),
   337  
   338  		// json contains
   339  		fmt.Sprintf("json_contains (%s['list'], 2)", common.DefaultJSONFieldName),
   340  		fmt.Sprintf("json_contains (%s['number'], 0)", common.DefaultJSONFieldName),
   341  		fmt.Sprintf("json_contains_all (%s['list'], [1, 2])", common.DefaultJSONFieldName),
   342  		fmt.Sprintf("JSON_CONTAINS_ANY (%s['list'], [1, 3])", common.DefaultJSONFieldName),
   343  		// string like
   344  		"dynamicString like '1%' ",
   345  
   346  		// key exist
   347  		fmt.Sprintf("exists %s['list']", common.DefaultJSONFieldName),
   348  		fmt.Sprintf("exists a "),
   349  		fmt.Sprintf("exists %s ", common.DefaultDynamicListField),
   350  		fmt.Sprintf("exists %s ", common.DefaultDynamicStringField),
   351  		// data type not match and no error
   352  		fmt.Sprintf("%s['number'] == '0' ", common.DefaultJSONFieldName),
   353  	}
   354  
   355  	for _, _exprCount := range exprCounts {
   356  		err := mc.Delete(ctx, collName, "", _exprCount)
   357  		common.CheckErr(t, err, true)
   358  
   359  		// query
   360  		countRes, _ := mc.Query(ctx, collName, []string{common.DefaultPartition}, _exprCount, []string{common.QueryCountFieldName})
   361  		require.Equal(t, int64(0), countRes.GetColumn(common.QueryCountFieldName).(*entity.ColumnInt64).Data()[0])
   362  	}
   363  }
   364  
   365  func TestDeleteInvalidExpr(t *testing.T) {
   366  	t.Parallel()
   367  	ctx := createContext(t, time.Second*common.DefaultTimeout)
   368  	// connect
   369  	mc := createMilvusClient(ctx, t)
   370  
   371  	// create collection
   372  	cp := CollectionParams{
   373  		CollectionFieldsType: Int64FloatVecJSON,
   374  		AutoID:               false,
   375  		EnableDynamicField:   true,
   376  		ShardsNum:            common.DefaultShards,
   377  		Dim:                  common.DefaultDim,
   378  	}
   379  	collName := createCollection(ctx, t, mc, cp)
   380  
   381  	// insert
   382  	dp := DataParams{
   383  		CollectionName:       collName,
   384  		PartitionName:        "",
   385  		CollectionFieldsType: Int64FloatVecJSON,
   386  		start:                0,
   387  		nb:                   common.DefaultNb,
   388  		dim:                  common.DefaultDim,
   389  		EnableDynamicField:   true,
   390  	}
   391  	_, _ = insertData(ctx, t, mc, dp)
   392  
   393  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 96)
   394  	_ = mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
   395  
   396  	err := mc.LoadCollection(ctx, collName, false)
   397  	common.CheckErr(t, err, true)
   398  
   399  	err = mc.Delete(ctx, collName, "", "")
   400  	common.CheckErr(t, err, false, "delete plan can't be empty or always true")
   401  
   402  	for _, _invalidExprs := range common.InvalidExpressions {
   403  		err := mc.Delete(ctx, collName, "", _invalidExprs.Expr)
   404  		common.CheckErr(t, err, _invalidExprs.ErrNil, _invalidExprs.ErrMsg)
   405  	}
   406  }
   407  
   408  func TestDeleteComplexExprWithoutLoading(t *testing.T) {
   409  	// TODO
   410  	ctx := createContext(t, time.Second*common.DefaultTimeout*3)
   411  	// connect
   412  	mc := createMilvusClient(ctx, t)
   413  
   414  	cp := CollectionParams{CollectionFieldsType: Int64FloatVecJSON, AutoID: false, EnableDynamicField: true,
   415  		ShardsNum: common.DefaultShards, Dim: common.DefaultDim}
   416  	collName := createCollection(ctx, t, mc, cp, client.WithConsistencyLevel(entity.ClStrong))
   417  
   418  	// prepare and insert data
   419  	dp := DataParams{CollectionName: collName, PartitionName: "", CollectionFieldsType: Int64FloatVecJSON,
   420  		start: 0, nb: common.DefaultNb, dim: common.DefaultDim, EnableDynamicField: true, WithRows: false}
   421  	_, _ = insertData(ctx, t, mc, dp)
   422  	mc.Flush(ctx, collName, false)
   423  
   424  	err := mc.Delete(ctx, collName, "", "int64 < 100")
   425  	common.CheckErr(t, err, false, "collection not loaded")
   426  
   427  	// load
   428  	idx, _ := entity.NewIndexHNSW(entity.L2, 8, 72)
   429  	_ = mc.CreateIndex(ctx, collName, common.DefaultFloatVecFieldName, idx, false)
   430  	err = mc.LoadCollection(ctx, collName, false)
   431  	common.CheckErr(t, err, true)
   432  
   433  	err = mc.Delete(ctx, collName, "", "int64 < 100")
   434  	common.CheckErr(t, err, true)
   435  }