Browse Source

Resolve conflict

tumao 3 years ago
parent
commit
896a8e53b2

+ 12 - 1
client/src/http/Collection.ts

@@ -1,5 +1,9 @@
 import { ChildrenStatusType } from '../components/status/Types';
-import { CollectionView, InsertDataParam } from '../pages/collections/Types';
+import {
+  CollectionView,
+  DeleteEntitiesReq,
+  InsertDataParam,
+} from '../pages/collections/Types';
 import { Field } from '../pages/schema/Types';
 import { VectorSearchParam } from '../pages/seach/Types';
 import { QueryParam } from '../pages/query/Types';
@@ -85,6 +89,13 @@ export class CollectionHttp extends BaseModel implements CollectionView {
     });
   }
 
+  static deleteEntities(collectionName: string, param: DeleteEntitiesReq) {
+    return super.update({
+      path: `${this.COLLECTIONS_URL}/${collectionName}/entities`,
+      data: param,
+    });
+  }
+
   static vectorSearchData(collectionName: string, params: VectorSearchParam) {
     return super.query({
       path: `${this.COLLECTIONS_URL}/${collectionName}/search`,

+ 2 - 0
client/src/i18n/cn/collection.ts

@@ -12,6 +12,7 @@ const collectionTrans = {
   aliasTooltip: 'Please select one collection to create alias',
 
   collection: 'Collection',
+  entites: 'entites',
 
   // table
   id: 'ID',
@@ -54,6 +55,7 @@ const collectionTrans = {
   // delete dialog
   deleteWarning:
     'You are trying to delete a collection with data. This action cannot be undone.',
+  deleteDataWarning: `You are trying to delete entites. This action cannot be undone.`,
 
   // collection tabs
   partitionTab: 'Partitions',

+ 3 - 2
client/src/i18n/en/collection.ts

@@ -12,6 +12,7 @@ const collectionTrans = {
   aliasTooltip: 'Please select one collection to create alias',
 
   collection: 'Collection',
+  entites: 'entites',
 
   // table
   id: 'ID',
@@ -52,8 +53,8 @@ const collectionTrans = {
   releaseConfirmLabel: 'Release',
 
   // delete dialog
-  deleteWarning:
-    'You are trying to delete a collection with data. This action cannot be undone.',
+  deleteWarning: `You are trying to delete a collection with data. This action cannot be undone.`,
+  deleteDataWarning: `You are trying to delete entites. This action cannot be undone.`,
 
   // collection tabs
   partitionTab: 'Partitions',

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

@@ -91,3 +91,8 @@ export interface InsertDataParam {
   // e.g. [{vector: [1,2,3], age: 10}]
   fields_data: any[];
 }
+
+export interface DeleteEntitiesReq {
+  expr: string;
+  partition_name?: string;
+}

+ 68 - 8
client/src/pages/query/Query.tsx

@@ -1,16 +1,21 @@
-import { FC, useEffect, useState, useRef, useMemo } from 'react';
+import { FC, useEffect, useState, useRef, useMemo, useContext } from 'react';
 import { useTranslation } from 'react-i18next';
 
+import { rootContext } from '../../context/Root';
+
 import EmptyCard from '../../components/cards/EmptyCard';
 import icons from '../../components/icons/Icons';
 import CustomButton from '../../components/customButton/CustomButton';
 import MilvusGrid from '../../components/grid/Grid';
+import { ToolBarConfig } from '../../components/grid/Types';
 import { getQueryStyles } from './Styles';
 import Filter from '../../components/advancedSearch';
 import { CollectionHttp } from '../../http/Collection';
 import { FieldHttp } from '../../http/Field';
 import { usePaginationHook } from '../../hooks/Pagination';
 import CopyButton from '../../components/advancedSearch/CopyButton';
+import DeleteTemplate from '../../components/customDialog/DeleteDialogTemplate';
+import CustomToolBar from '../../components/grid/ToolBar';
 
 const Query: FC<{
   collectionName: string;
@@ -19,10 +24,16 @@ const Query: FC<{
   const [expression, setExpression] = useState('');
   const [tableLoading, setTableLoading] = useState<any>();
   const [queryResult, setQueryResult] = useState<any>();
+  const [selectedDatas, setSelectedDatas] = useState<any[]>([]);
+  const [primaryKey, setPrimaryKey] = useState<string>('');
 
+  const { setDialog, handleCloseDialog, openSnackBar } =
+    useContext(rootContext);
   const VectorSearchIcon = icons.vectorSearch;
   const ResetIcon = icons.refresh;
 
+  const { t: dialogTrans } = useTranslation('dialog');
+  const { t: successTrans } = useTranslation('success');
   const { t: searchTrans } = useTranslation('search');
   const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
@@ -80,10 +91,13 @@ const Query: FC<{
 
   const getFields = async (collectionName: string) => {
     const schemaList = await FieldHttp.getFields(collectionName);
-    const nameList = schemaList.map(i => ({
-      name: i.name,
-      type: i.data_type.includes('Int') ? 'int' : 'float',
+    const nameList = schemaList.map(v => ({
+      name: v.name,
+      type: v.data_type.includes('Int') ? 'int' : 'float',
     }));
+    const primaryKey =
+      schemaList.find(v => v._isPrimaryKey === true)?._fieldName || '';
+    setPrimaryKey(primaryKey);
     setFields(nameList);
   };
 
@@ -101,10 +115,12 @@ const Query: FC<{
     setTableLoading(null);
     setQueryResult(null);
   };
+
   const handleFilterSubmit = (expression: string) => {
     setExpression(expression);
     setQueryResult(null);
   };
+
   const handleQuery = async () => {
     setTableLoading(true);
     try {
@@ -121,13 +137,55 @@ const Query: FC<{
     }
   };
 
+  const handleSelectChange = (value: any) => {
+    setSelectedDatas(value);
+  };
+
+  const handleDelete = async () => {
+    await CollectionHttp.deleteEntities(collectionName, {
+      expr: `${primaryKey} in [${selectedDatas.map(v => v.id).join(',')}]`,
+    });
+    handleCloseDialog();
+    openSnackBar(successTrans('delete', { name: collectionTrans('entites') }));
+    handleQuery();
+  };
+
+  const toolbarConfigs: ToolBarConfig[] = [
+    {
+      type: 'iconBtn',
+      onClick: () => {
+        setDialog({
+          open: true,
+          type: 'custom',
+          params: {
+            component: (
+              <DeleteTemplate
+                label={btnTrans('delete')}
+                title={dialogTrans('deleteTitle', {
+                  type: collectionTrans('entites'),
+                })}
+                text={collectionTrans('deleteDataWarning')}
+                handleDelete={handleDelete}
+              />
+            ),
+          },
+        });
+      },
+      label: collectionTrans('delete'),
+      icon: 'delete',
+      // tooltip: collectionTrans('deleteTooltip'),
+      disabledTooltip: collectionTrans('deleteTooltip'),
+      disabled: () => selectedDatas.length === 0,
+    },
+  ];
+
   return (
     <div className={classes.root}>
+      <CustomToolBar toolbarConfigs={toolbarConfigs} />
+
       <div className={classes.toolbar}>
         <div className="left">
-          <div>{`${
-            expression || collectionTrans('exprPlaceHolder')
-          }`}</div>
+          <div>{`${expression || collectionTrans('exprPlaceHolder')}`}</div>
           <Filter
             ref={filterRef}
             title="Advanced Filter"
@@ -162,10 +220,12 @@ const Query: FC<{
             label: i.name,
           }))}
           primaryKey={fields.find(i => i.is_primary_key)?.name}
-          openCheckBox={false}
+          openCheckBox={true}
           isLoading={!!tableLoading}
           rows={result}
           rowCount={total}
+          selected={selectedDatas}
+          setSelected={handleSelectChange}
           page={currentPage}
           onChangePage={handlePageChange}
           rowsPerPage={pageSize}

+ 17 - 0
express/src/collections/collections.controller.ts

@@ -59,6 +59,9 @@ export class CollectionController {
       this.insert.bind(this)
     );
 
+    // we need use req.body, so we can't use delete here
+    this.router.put("/:name/entities", this.deleteEntities.bind(this));
+
     this.router.post(
       "/:name/search",
       dtoValidationMiddleware(VectorSearchDto),
@@ -205,6 +208,20 @@ export class CollectionController {
     }
   }
 
+  async deleteEntities(req: Request, res: Response, next: NextFunction) {
+    const name = req.params?.name;
+    const data = req.body;
+    try {
+      const result = await this.collectionsService.deleteEntities({
+        collection_name: name,
+        ...data,
+      });
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
+
   async vectorSearch(req: Request, res: Response, next: NextFunction) {
     const name = req.params?.name;
     const data = req.body;

+ 6 - 0
express/src/collections/collections.service.ts

@@ -21,6 +21,7 @@ import {
   ShowCollectionsType,
 } from '@zilliz/milvus2-sdk-node/dist/milvus/types/Collection';
 import { QueryDto } from './dto';
+import { DeleteEntitiesReq } from '@zilliz/milvus2-sdk-node/dist/milvus/types/Data';
 
 export class CollectionsService {
   constructor(private milvusService: MilvusService) {}
@@ -85,6 +86,11 @@ export class CollectionsService {
     return res;
   }
 
+  async deleteEntities(data: DeleteEntitiesReq) {
+    const res = await this.dataManager.deleteEntities(data);
+    return res;
+  }
+
   async vectorSearch(data: SearchReq) {
     const res = await this.dataManager.search(data);
     throwErrorFromSDK(res.status);