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 }