Browse Source

Add empty data dialog (#360)

* add empty dialog client

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* support empty data

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

---------

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 1 year ago
parent
commit
c9863ed648

+ 17 - 7
client/src/components/customDialog/DeleteDialogTemplate.tsx

@@ -20,6 +20,9 @@ const useStyles = makeStyles((theme: Theme) => ({
     maxWidth: '480px',
     maxWidth: '480px',
     backgroundColor: '#fff',
     backgroundColor: '#fff',
   },
   },
+  info: {
+    marginBottom: theme.spacing(0.5),
+  },
   mb: {
   mb: {
     marginBottom: theme.spacing(2.5),
     marginBottom: theme.spacing(2.5),
   },
   },
@@ -42,8 +45,15 @@ const useStyles = makeStyles((theme: Theme) => ({
 }));
 }));
 
 
 const DeleteTemplate: FC<DeleteDialogContentType> = props => {
 const DeleteTemplate: FC<DeleteDialogContentType> = props => {
-  const { title, text, label, handleDelete, handleCancel, forceDelLabel } =
-    props;
+  const {
+    title,
+    text,
+    label,
+    compare,
+    handleDelete,
+    handleCancel,
+    forceDelLabel,
+  } = props;
   const { handleCloseDialog } = useContext(rootContext);
   const { handleCloseDialog } = useContext(rootContext);
   const classes = useStyles();
   const classes = useStyles();
   const { t: dialogTrans } = useTranslation('dialog');
   const { t: dialogTrans } = useTranslation('dialog');
@@ -67,7 +77,7 @@ const DeleteTemplate: FC<DeleteDialogContentType> = props => {
     const value = event.target.value;
     const value = event.target.value;
     setValue(value);
     setValue(value);
 
 
-    setDeleteReady(value.toLowerCase() === label.toLowerCase());
+    setDeleteReady(value.toLowerCase() === (compare || label).toLowerCase());
   };
   };
 
 
   return (
   return (
@@ -81,12 +91,12 @@ const DeleteTemplate: FC<DeleteDialogContentType> = props => {
         </CustomDialogTitle>
         </CustomDialogTitle>
 
 
         <DialogContent>
         <DialogContent>
-          <Typography variant="body1">{text}</Typography>
+          <Typography variant="body1" className={classes.info}>{text}</Typography>
           <Typography variant="body1" className={classes.mb}>
           <Typography variant="body1" className={classes.mb}>
             {dialogTrans('deleteTipAction')}
             {dialogTrans('deleteTipAction')}
-            <strong
-              className={classes.btnLabel}
-            >{` ${label.toLowerCase()} `}</strong>
+            <strong className={classes.btnLabel}>{` ${(
+              compare || label
+            ).toLowerCase()} `}</strong>
             {dialogTrans('deleteTipPurpose')}
             {dialogTrans('deleteTipPurpose')}
           </Typography>
           </Typography>
           <TextField
           <TextField

+ 1 - 0
client/src/components/customDialog/Types.ts

@@ -17,6 +17,7 @@ export type DeleteDialogContentType = {
   title: string;
   title: string;
   text: string;
   text: string;
   label: string;
   label: string;
+  compare?: string;
   handleCancel?: () => void;
   handleCancel?: () => void;
   handleDelete: (force?: boolean) => void;
   handleDelete: (force?: boolean) => void;
   forceDelLabel?: string;
   forceDelLabel?: string;

+ 2 - 3
client/src/components/grid/ToolBar.tsx

@@ -25,8 +25,7 @@ const useStyles = makeStyles((theme: Theme) =>
       opacity: 0.4,
       opacity: 0.4,
     },
     },
     btn: {
     btn: {
-      // marginLeft: theme.spacing(1),
-      marginRight: '12px',
+      marginRight:  theme.spacing(.5),
     },
     },
     gridEnd: {
     gridEnd: {
       display: 'flex',
       display: 'flex',
@@ -83,7 +82,7 @@ const CustomToolBar: FC<ToolBarType> = props => {
                 size="small"
                 size="small"
                 onClick={c.onClick}
                 onClick={c.onClick}
                 startIcon={Icon}
                 startIcon={Icon}
-                color="primary"
+                color={c.btnColor || 'primary'}
                 disabled={disabled}
                 disabled={disabled}
                 // use contained variant as default
                 // use contained variant as default
                 variant={c.btnVariant || 'contained'}
                 variant={c.btnVariant || 'contained'}

+ 1 - 0
client/src/components/grid/Types.ts

@@ -46,6 +46,7 @@ export type ToolBarConfig = Partial<TableSwitchType> &
     position?: 'right' | 'left';
     position?: 'right' | 'left';
     component?: ReactElement;
     component?: ReactElement;
     btnVariant?: 'contained' | 'outlined' | 'text';
     btnVariant?: 'contained' | 'outlined' | 'text';
+    btnColor?: 'primary' | 'secondary'
   };
   };
 
 
 export type TableHeadType = {
 export type TableHeadType = {

+ 2 - 0
client/src/components/icons/Icons.tsx

@@ -4,6 +4,7 @@ import SearchIcon from '@material-ui/icons/Search';
 import AddIcon from '@material-ui/icons/Add';
 import AddIcon from '@material-ui/icons/Add';
 import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutlineOutlined';
 import AddCircleOutlineIcon from '@material-ui/icons/AddCircleOutlineOutlined';
 import DeleteIcon from '@material-ui/icons/Delete';
 import DeleteIcon from '@material-ui/icons/Delete';
+import DeleteOutlineIcon from '@material-ui/icons/DeleteOutline';
 import FileCopyIcon from '@material-ui/icons/FileCopy';
 import FileCopyIcon from '@material-ui/icons/FileCopy';
 import Visibility from '@material-ui/icons/Visibility';
 import Visibility from '@material-ui/icons/Visibility';
 import VisibilityOff from '@material-ui/icons/VisibilityOff';
 import VisibilityOff from '@material-ui/icons/VisibilityOff';
@@ -49,6 +50,7 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
   add: (props = {}) => <AddIcon {...props} />,
   add: (props = {}) => <AddIcon {...props} />,
   addOutline: (props = {}) => <AddCircleOutlineIcon {...props} />,
   addOutline: (props = {}) => <AddCircleOutlineIcon {...props} />,
   delete: (props = {}) => <DeleteIcon {...props} />,
   delete: (props = {}) => <DeleteIcon {...props} />,
+  deleteOutline: (props = {}) => <DeleteOutlineIcon {...props} />,
   list: (props = {}) => <ReorderIcon {...props} />,
   list: (props = {}) => <ReorderIcon {...props} />,
   copy: (props = {}) => <FileCopyIcon {...props} />,
   copy: (props = {}) => <FileCopyIcon {...props} />,
   visible: (props = {}) => <Visibility {...props} />,
   visible: (props = {}) => <Visibility {...props} />,

+ 1 - 0
client/src/components/icons/Types.ts

@@ -3,6 +3,7 @@ export type IconsType =
   | 'add'
   | 'add'
   | 'addOutline'
   | 'addOutline'
   | 'delete'
   | 'delete'
+  | 'deleteOutline'
   | 'list'
   | 'list'
   | 'copy'
   | 'copy'
   | 'visible'
   | 'visible'

+ 6 - 0
client/src/http/Data.service.ts

@@ -41,4 +41,10 @@ export class DataService extends BaseModel {
       },
       },
     });
     });
   }
   }
+
+  static emptyData(collectionName: string) {
+    return super.update({
+      path: `${this.COLLECTIONS_URL}/${collectionName}/empty`,
+    });
+  }
 }
 }

+ 1 - 0
client/src/i18n/cn/button.ts

@@ -26,6 +26,7 @@ const btnTrans = {
   rename: '重命名',
   rename: '重命名',
   duplicate: '复制',
   duplicate: '复制',
   export: '导出',
   export: '导出',
+  empty: '清空数据'
 };
 };
 
 
 export default btnTrans;
 export default btnTrans;

+ 6 - 1
client/src/i18n/cn/collection.ts

@@ -18,6 +18,8 @@ const collectionTrans = {
   download: '下载',
   download: '下载',
   downloadTooltip: '将所有查询结果导出到CSV文件',
   downloadTooltip: '将所有查询结果导出到CSV文件',
   downloadDisabledTooltip: '请在导出前查询数据',
   downloadDisabledTooltip: '请在导出前查询数据',
+  empty: '清空数据',
+  emptyDataDisableTooltip: '请选择一个已加载的Collection进行清空数据操作',
 
 
   collection: 'Collection',
   collection: 'Collection',
   entities: 'Entities',
   entities: 'Entities',
@@ -37,7 +39,8 @@ const collectionTrans = {
   aliasInfo: '别名可以在向量搜索中用作Collection名称。',
   aliasInfo: '别名可以在向量搜索中用作Collection名称。',
   consistencyLevelInfo:
   consistencyLevelInfo:
     '一致性是指确保每个节点或副本在给定时间写入或读取数据时具有相同数据视图的属性。',
     '一致性是指确保每个节点或副本在给定时间写入或读取数据时具有相同数据视图的属性。',
-  entityCountInfo: '大约的Entity数量。',
+  entityCountInfo:
+    '这个计数是一个近似值,并可能因为Milvus的独特机制而稍有延迟。实际的计数可能会有所变化,并会定期更新。请注意,这个数字应该被用作参考,而不是精确的计数。',
   duplicateCollectionInfo:
   duplicateCollectionInfo:
     '复制Collection不会复制Collection中的数据。它只会使用现有的Schema创建一个新的Collection。',
     '复制Collection不会复制Collection中的数据。它只会使用现有的Schema创建一个新的Collection。',
 
 
@@ -147,6 +150,8 @@ const collectionTrans = {
   // flush dialog
   // flush dialog
   flush: '落盘',
   flush: '落盘',
   flushDialogInfo: `落盘是一个在数据被插入到Milvus后,封闭和索引任何剩余段的过程。这避免了在未封闭的段上进行暴力搜索。  <br /><br />最好在插入会话结束时使用落盘,以防止数据碎片化。 <br /><br /><strong>注意:对于大型数据集,此操作可能需要一些时间。</strong>`,
   flushDialogInfo: `落盘是一个在数据被插入到Milvus后,封闭和索引任何剩余段的过程。这避免了在未封闭的段上进行暴力搜索。  <br /><br />最好在插入会话结束时使用落盘,以防止数据碎片化。 <br /><br /><strong>注意:对于大型数据集,此操作可能需要一些时间。</strong>`,
+
+  emptyDataDialogInfo: `您正在尝试清空数据。此操作无法撤销,请谨慎操作。`,
 };
 };
 
 
 export default collectionTrans;
 export default collectionTrans;

+ 1 - 0
client/src/i18n/cn/dialog.ts

@@ -14,6 +14,7 @@ const dialogTrans = {
   releaseContent: `您正在尝试发布带有数据的 {{type}}。请注意,数据将不再可用于搜索。`,
   releaseContent: `您正在尝试发布带有数据的 {{type}}。请注意,数据将不再可用于搜索。`,
 
 
   createTitle: `在 "{{name}}" 上创建 {{type}}`,
   createTitle: `在 "{{name}}" 上创建 {{type}}`,
+  emptyTitle: `清空{{type}}的数据`,
 };
 };
 
 
 export default dialogTrans;
 export default dialogTrans;

+ 1 - 0
client/src/i18n/cn/success.ts

@@ -7,6 +7,7 @@ const successTrans = {
   update: `{{name}}更新成功。`,
   update: `{{name}}更新成功。`,
   rename: `{{name}}重命名成功。`,
   rename: `{{name}}重命名成功。`,
   duplicate: `{{name}}复制成功.`,
   duplicate: `{{name}}复制成功.`,
+  empty: `{{name}}清空已经开始.`,
 };
 };
 
 
 export default successTrans;
 export default successTrans;

+ 2 - 1
client/src/i18n/en/button.ts

@@ -25,7 +25,8 @@ const btnTrans = {
   example: 'Generate Random Vector',
   example: 'Generate Random Vector',
   rename: 'Rename',
   rename: 'Rename',
   duplicate: 'Duplicate',
   duplicate: 'Duplicate',
-  export: 'Export'
+  export: 'Export',
+  empty: 'Empty'
 };
 };
 
 
 export default btnTrans;
 export default btnTrans;

+ 7 - 1
client/src/i18n/en/collection.ts

@@ -18,6 +18,8 @@ const collectionTrans = {
   download: 'Download',
   download: 'Download',
   downloadTooltip: 'Export all query results to CSV file',
   downloadTooltip: 'Export all query results to CSV file',
   downloadDisabledTooltip: 'Please query data before exporting',
   downloadDisabledTooltip: 'Please query data before exporting',
+  empty: 'empty data',
+  emptyDataDisableTooltip: 'Please select one loaded collection to empty data',
 
 
   collection: 'Collection',
   collection: 'Collection',
   entities: 'entities',
   entities: 'entities',
@@ -37,7 +39,8 @@ const collectionTrans = {
   aliasInfo: 'Alias can be used as collection name in vector search.',
   aliasInfo: 'Alias can be used as collection name in vector search.',
   consistencyLevelInfo:
   consistencyLevelInfo:
     'Consistency refers to the property that ensures every node or replica has the same view of data when writing or reading data at a given time.',
     'Consistency refers to the property that ensures every node or replica has the same view of data when writing or reading data at a given time.',
-  entityCountInfo: 'Approximately entity count.',
+  entityCountInfo:
+    'This count is an approximation and may be slightly delayed due to the unique mechanisms of Milvus. The actual count may vary and is updated periodically. Please note that this number should be used as a reference and not as an exact count.',
   duplicateCollectionInfo:
   duplicateCollectionInfo:
     'Duplicating a collection does not copy the data within the collection. It only creates a new collection using the existing schema.',
     'Duplicating a collection does not copy the data within the collection. It only creates a new collection using the existing schema.',
 
 
@@ -146,6 +149,9 @@ const collectionTrans = {
   // flush dialog
   // flush dialog
   flush: 'Flush',
   flush: 'Flush',
   flushDialogInfo: `Flush is a process that seals and indexes any remaining segments after data is upserted into Milvus. This avoids brute force searches on unsealed segments.  <br /><br />It's best to use flush at the end of an upsert session to prevent data fragmentation. <br /><br /><strong>Note: that this operation may take some time for large datasets.</strong>`,
   flushDialogInfo: `Flush is a process that seals and indexes any remaining segments after data is upserted into Milvus. This avoids brute force searches on unsealed segments.  <br /><br />It's best to use flush at the end of an upsert session to prevent data fragmentation. <br /><br /><strong>Note: that this operation may take some time for large datasets.</strong>`,
+
+  // empty dialog
+  emptyDataDialogInfo: `You are attempting to empty the data. This action cannot be undone, please proceed with caution.`,
 };
 };
 
 
 export default collectionTrans;
 export default collectionTrans;

+ 1 - 0
client/src/i18n/en/dialog.ts

@@ -14,6 +14,7 @@ const dialogTrans = {
   releaseContent: `You are trying to release {{type}} with data. Please be aware that the data will no longer be available for search.`,
   releaseContent: `You are trying to release {{type}} with data. Please be aware that the data will no longer be available for search.`,
 
 
   createTitle: `Create {{type}} on "{{name}}"`,
   createTitle: `Create {{type}} on "{{name}}"`,
+  emptyTitle: `Empty data for {{type}}`,
 };
 };
 
 
 export default dialogTrans;
 export default dialogTrans;

+ 1 - 0
client/src/i18n/en/success.ts

@@ -7,6 +7,7 @@ const successTrans = {
   update: `{{name}} has been updated.`,
   update: `{{name}} has been updated.`,
   rename: `{{name}} has been renamed.`,
   rename: `{{name}} has been renamed.`,
   duplicate: `{{name}} has been duplicated.`,
   duplicate: `{{name}} has been duplicated.`,
+  empty: `Emptying data for {{name}} has started.`,
 };
 };
 
 
 export default successTrans;
 export default successTrans;

+ 56 - 12
client/src/pages/collections/Collections.tsx

@@ -26,6 +26,7 @@ import ReleaseCollectionDialog from '../dialogs/ReleaseCollectionDialog';
 import DropCollectionDialog from '../dialogs/DropCollectionDialog';
 import DropCollectionDialog from '../dialogs/DropCollectionDialog';
 import RenameCollectionDialog from '../dialogs/RenameCollectionDialog';
 import RenameCollectionDialog from '../dialogs/RenameCollectionDialog';
 import DuplicateCollectionDialog from '../dialogs/DuplicateCollectionDailog';
 import DuplicateCollectionDialog from '../dialogs/DuplicateCollectionDailog';
+import EmptyDataDialog from '../dialogs/EmptyDataDialog';
 import InsertDialog from '../dialogs/insert/Dialog';
 import InsertDialog from '../dialogs/insert/Dialog';
 import ImportSampleDialog from '../dialogs/ImportSampleDialog';
 import ImportSampleDialog from '../dialogs/ImportSampleDialog';
 import { LOADING_STATE } from '@/consts';
 import { LOADING_STATE } from '@/consts';
@@ -299,7 +300,9 @@ const Collections = () => {
     },
     },
     {
     {
       icon: 'uploadFile',
       icon: 'uploadFile',
-      type: 'iconBtn',
+      type: 'button',
+      btnVariant: 'text',
+      btnColor: 'secondary',
       label: btnTrans('insert'),
       label: btnTrans('insert'),
       onClick: () => {
       onClick: () => {
         setDialog({
         setDialog({
@@ -355,7 +358,9 @@ const Collections = () => {
     },
     },
     {
     {
       icon: 'edit',
       icon: 'edit',
-      type: 'iconBtn',
+      type: 'button',
+      btnColor: 'secondary',
+      btnVariant: 'text',
       onClick: () => {
       onClick: () => {
         setDialog({
         setDialog({
           open: true,
           open: true,
@@ -378,14 +383,15 @@ const Collections = () => {
           },
           },
         });
         });
       },
       },
-      label: collectionTrans('rename'),
+      label: btnTrans('rename'),
       // tooltip: collectionTrans('deleteTooltip'),
       // tooltip: collectionTrans('deleteTooltip'),
       disabledTooltip: collectionTrans('renameTooltip'),
       disabledTooltip: collectionTrans('renameTooltip'),
       disabled: data => data.length !== 1,
       disabled: data => data.length !== 1,
     },
     },
     {
     {
       icon: 'copy',
       icon: 'copy',
-      type: 'iconBtn',
+      type: 'button',
+      btnVariant: 'text',
       onClick: () => {
       onClick: () => {
         setDialog({
         setDialog({
           open: true,
           open: true,
@@ -409,13 +415,51 @@ const Collections = () => {
           },
           },
         });
         });
       },
       },
-      label: collectionTrans('duplicate'),
+      label: btnTrans('duplicate'),
       // tooltip: collectionTrans('deleteTooltip'),
       // tooltip: collectionTrans('deleteTooltip'),
       disabledTooltip: collectionTrans('duplicateTooltip'),
       disabledTooltip: collectionTrans('duplicateTooltip'),
       disabled: data => data.length !== 1,
       disabled: data => data.length !== 1,
     },
     },
     {
     {
-      type: 'iconBtn',
+      icon: 'deleteOutline',
+      type: 'button',
+      btnVariant: 'text',
+      onClick: () => {
+        setDialog({
+          open: true,
+          type: 'custom',
+          params: {
+            component: (
+              <EmptyDataDialog
+                cb={async () => {
+                  openSnackBar(
+                    successTrans('empty', {
+                      name: collectionTrans('collection'),
+                    })
+                  );
+                  setSelectedCollections([]);
+                  await fetchData();
+                }}
+                collectionName={selectedCollections[0].collectionName}
+              />
+            ),
+          },
+        });
+      },
+      label: btnTrans('empty'),
+      disabledTooltip: collectionTrans('emptyDataDisableTooltip'),
+      disabled: (data: any) => {
+        if (data.length === 0 || data.length > 1) {
+          return true;
+        } else {
+          return Number(data[0].loadedPercentage) !== 100;
+        }
+      },
+    },
+    {
+      icon: 'delete',
+      type: 'button',
+      btnVariant: 'text',
       onClick: () => {
       onClick: () => {
         setDialog({
         setDialog({
           open: true,
           open: true,
@@ -438,21 +482,21 @@ const Collections = () => {
           },
           },
         });
         });
       },
       },
-      label: collectionTrans('delete'),
-      icon: 'delete',
+      label: btnTrans('drop'),
       // tooltip: collectionTrans('deleteTooltip'),
       // tooltip: collectionTrans('deleteTooltip'),
       disabledTooltip: collectionTrans('deleteTooltip'),
       disabledTooltip: collectionTrans('deleteTooltip'),
-      disabled: data => data.length === 0,
+      disabled: data => data.length !== 1,
     },
     },
 
 
     {
     {
-      type: 'iconBtn',
+      icon: 'refresh',
+      type: 'button',
+      btnVariant: 'text',
       onClick: () => {
       onClick: () => {
         clearIndexCache();
         clearIndexCache();
         fetchData();
         fetchData();
       },
       },
-      label: collectionTrans('delete'),
-      icon: 'refresh',
+      label: btnTrans('refresh'),
     },
     },
 
 
     {
     {

+ 37 - 0
client/src/pages/dialogs/EmptyDataDialog.tsx

@@ -0,0 +1,37 @@
+import { FC, useContext } from 'react';
+import { useTranslation } from 'react-i18next';
+import { rootContext } from '@/context';
+import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
+import { DataService } from '@/http';
+import { EmptyDataProps } from './Types';
+
+const EmptyDataDialog: FC<EmptyDataProps> = props => {
+  const { cb, collectionName } = props;
+
+  const { handleCloseDialog } = useContext(rootContext);
+  const { t: dialogTrans } = useTranslation('dialog');
+  const { t: collectionTrans } = useTranslation('collection');
+  const { t: btnTrans } = useTranslation('btn');
+
+  const handleDelete = async () => {
+    // duplicate
+    DataService.emptyData(collectionName);
+    // close dialog
+    handleCloseDialog();
+    cb && cb();
+  };
+
+  return (
+    <DeleteTemplate
+      label={btnTrans('empty')}
+      title={dialogTrans('emptyTitle', {
+        type: collectionTrans('collection'),
+      })}
+      compare={collectionName}
+      text={collectionTrans('emptyDataDialogInfo')}
+      handleDelete={handleDelete}
+    />
+  );
+};
+
+export default EmptyDataDialog;

+ 5 - 0
client/src/pages/dialogs/Types.ts

@@ -30,6 +30,11 @@ export interface CreateAliasProps {
   cb?: () => void;
   cb?: () => void;
 }
 }
 
 
+export interface EmptyDataProps {
+  collectionName: string;
+  cb?: () => void;
+}
+
 export interface DuplicateCollectionDialogProps extends CreateAliasProps {
 export interface DuplicateCollectionDialogProps extends CreateAliasProps {
   collections: Collection[];
   collections: Collection[];
 }
 }

+ 15 - 0
server/src/collections/collections.controller.ts

@@ -64,6 +64,8 @@ export class CollectionController {
     // load / release
     // load / release
     this.router.put('/:name/load', this.loadCollection.bind(this));
     this.router.put('/:name/load', this.loadCollection.bind(this));
     this.router.put('/:name/release', this.releaseCollection.bind(this));
     this.router.put('/:name/release', this.releaseCollection.bind(this));
+    this.router.put('/:name/empty', this.empty.bind(this));
+
     this.router.post(
     this.router.post(
       '/:name/insert',
       '/:name/insert',
       dtoValidationMiddleware(InsertDataDto),
       dtoValidationMiddleware(InsertDataDto),
@@ -425,4 +427,17 @@ export class CollectionController {
       next(error);
       next(error);
     }
     }
   }
   }
+
+  async empty(req: Request, res: Response, next: NextFunction) {
+    const name = req.params?.name;
+    try {
+      const result = await this.collectionsService.emptyCollection({
+        collection_name: name,
+      });
+
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
 }
 }

+ 12 - 0
server/src/collections/collections.service.ts

@@ -394,4 +394,16 @@ export class CollectionsService {
     console.dir(createCollectionParams, { depth: null });
     console.dir(createCollectionParams, { depth: null });
     return await this.createCollection(createCollectionParams);
     return await this.createCollection(createCollectionParams);
   }
   }
+
+  async emptyCollection(data: HasCollectionReq) {
+    const pkField = await MilvusService.activeMilvusClient.getPkFieldName(data);
+    const pkType = await MilvusService.activeMilvusClient.getPkFieldType(data);
+
+    const res = await MilvusService.activeMilvusClient.deleteEntities({
+      collection_name: data.collection_name,
+      filter: pkType === 'Int64' ? `${pkField} >= 0` : `${pkField} != ''`,
+    });
+
+    return res;
+  }
 }
 }