Browse Source

Merge pull request #266 from zilliztech/compact

add compact dialog
ryjiang 1 year ago
parent
commit
d4ee7d5bf5

+ 3 - 0
client/src/assets/icons/compact.svg

@@ -0,0 +1,3 @@
+<svg focusable="false" aria-hidden="true" viewBox="0 0 24 24" data-testid="CompressIcon">
+  <path d="M8 19h3v3h2v-3h3l-4-4-4 4zm8-15h-3V1h-2v3H8l4 4 4-4zM4 9v2h16V9H4zm0 3h16v2H4z"></path>
+</svg>

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

@@ -42,6 +42,7 @@ import { ReactComponent as VectorSearchIcon } from '../../assets/icons/nav-searc
 import { ReactComponent as SearchEmptyIcon } from '../../assets/icons/search.svg';
 import { ReactComponent as CopyIcon } from '../../assets/icons/copy.svg';
 import { ReactComponent as SystemIcon } from '../../assets/icons/system.svg';
+import { ReactComponent as Compact } from '../../assets/icons/compact.svg';
 
 const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
   search: (props = {}) => <SearchIcon {...props} />,
@@ -196,6 +197,9 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
       <path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11zM8 15.01l1.41 1.41L11 14.84V19h2v-4.16l1.59 1.59L16 15.01 12.01 11z"></path>
     </SvgIcon>
   ),
+  compact: (props = {}) => (
+    <SvgIcon viewBox="0 0 24 24" component={Compact} {...props} />
+  ),
 };
 
 export default icons;

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

@@ -41,4 +41,5 @@ export type IconsType =
   | 'source'
   | 'edit'
   | 'database'
-  | 'uploadFile';
+  | 'uploadFile'
+  | 'compact';

+ 7 - 0
client/src/http/Collection.ts

@@ -159,6 +159,12 @@ export class CollectionHttp extends BaseModel implements CollectionView {
     });
   }
 
+  static compact(collectionName: string) {
+    return super.update({
+      path: `${this.COLLECTIONS_URL}/${collectionName}/compact`,
+    });
+  }
+
   get _autoId() {
     return this.autoID;
   }
@@ -227,4 +233,5 @@ export class CollectionHttp extends BaseModel implements CollectionView {
   get _replicas(): Replica[] {
     return this.replicas;
   }
+  
 }

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

@@ -48,7 +48,7 @@ const collectionTrans = {
   vectorFieldName: 'Vector Field',
   autoId: 'Auto ID',
   autoIdToggleTip:
-    'Whether the primary key is automatically generated by Milvus, only suppport INT64.',
+    'Whether the primary key is automatically generated by Milvus, only support INT64.',
   vectorType: 'Type',
   idType: 'Type',
   dimension: 'Dimension',
@@ -62,7 +62,7 @@ const collectionTrans = {
     'Name first character must be underscore or character(a~z, A~Z)',
   partitionKey: 'Partition Key',
   partitionKeyTooltip:
-    ' Milvus will store entities in a partition according to the values in the partition key field. Only one Int64 or VarChar field is suppported.',
+    ' Milvus will store entities in a partition according to the values in the partition key field. Only one Int64 or VarChar field is supported.',
 
   // load dialog
   loadTitle: 'Load Collection',
@@ -102,8 +102,8 @@ const collectionTrans = {
   newColNamePlaceholder: 'New Collection Name',
   newNameInfo: 'Only numbers, letters, and underscores are allowed.',
 
-  // segement
-  segements: 'Segments',
+  // segment
+  segments: 'Segments',
   segPState: 'Persistent Segment State',
   partitionID: 'Partition ID',
   segmentID: 'Segment ID',
@@ -113,6 +113,9 @@ const collectionTrans = {
   q_indexID: 'Index ID',
   q_state: 'Query Segment State',
   q_mem_size: 'Memory Size',
+  compact: 'Compact',
+  compactDialogInfo: `Compaction is a process that optimizes storage and query performance by organizing segments.  <a href='https://milvus.io/blog/2022-2-21-compact.md' target="_blank">Learn more</a><br /><br />  Please note that this operation may take some time to complete, especially for large datasets. We recommend running compaction during periods of lower system activity or during scheduled maintenance to minimize disruption.
+    `,
 };
 
 export default collectionTrans;

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

@@ -5,6 +5,7 @@ const dialogTrans = {
   renameTitle: `Rename {{type}}`,
   releaseTitle: `Release {{type}}`,
   createAlias: `Create alias for {{type}}`,
+  compact: `Compact collection {{type}}`,
   loadTitle: `Load {{type}}`,
 
   loadContent: `You are trying to load a {{type}} with data. Only loaded {{type}} can be searched.`,

+ 59 - 0
client/src/pages/dialogs/CompactDialog.tsx

@@ -0,0 +1,59 @@
+import { FC, useContext } from 'react';
+import { Typography, makeStyles, Theme } from '@material-ui/core';
+import { useTranslation } from 'react-i18next';
+import { rootContext } from '@/context';
+import DialogTemplate from '@/components/customDialog/DialogTemplate';
+import { CompactDialogProps } from './Types';
+import { CollectionHttp } from '@/http';
+
+const useStyles = makeStyles((theme: Theme) => ({
+  desc: {
+    margin: '8px 0 16px 0',
+    maxWidth: '500px'
+  },
+  dialog: {},
+}));
+
+const CompactDialog: FC<CompactDialogProps> = props => {
+  const { cb, collectionName } = props;
+
+  const classes = useStyles();
+
+  const { handleCloseDialog } = useContext(rootContext);
+  const { t: dialogTrans } = useTranslation('dialog');
+  const { t: warningTrans } = useTranslation('warning');
+  const { t: collectionTrans } = useTranslation('collection');
+  const { t: btnTrans } = useTranslation('btn');
+
+  const handleConfirm = async () => {
+    await CollectionHttp.compact(collectionName);
+
+    handleCloseDialog();
+    cb && cb();
+  };
+
+  const disabled = false;
+
+  return (
+    <DialogTemplate
+      dialogClass={classes.dialog}
+      title={dialogTrans('compact', {
+        type: collectionName,
+      })}
+      handleClose={handleCloseDialog}
+      children={
+        <>
+          <Typography variant="body1" component="p" className={classes.desc} dangerouslySetInnerHTML={{
+                __html: collectionTrans('compactDialogInfo'),
+              }}>
+          </Typography>
+        </>
+      }
+      confirmLabel={btnTrans('confirm')}
+      handleConfirm={handleConfirm}
+      confirmDisabled={disabled}
+    />
+  );
+};
+
+export default CompactDialog;

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

@@ -17,6 +17,13 @@ export interface PartitionCreateProps {
   collectionName: string;
 }
 
+interface CollectionDialogBaseProps {
+  collectionName: string;
+  cb?: () => void;
+}
+
+export interface CompactDialogProps extends CollectionDialogBaseProps {}
+
 export interface CreateAliasProps {
   collectionName: string;
   cb?: () => void;

+ 30 - 3
client/src/pages/segments/Segments.tsx

@@ -1,11 +1,13 @@
-import { useEffect, useState, FC } from 'react';
+import { useEffect, useState, FC, useContext } from 'react';
 import { useTranslation } from 'react-i18next';
 import { CollectionHttp } from '@/http';
 import { usePaginationHook } from '@/hooks';
+import { rootContext } from '@/context';
 import AttuGrid from '@/components/grid/Grid';
 import { ColDefinitionsType } from '@/components/grid/Types';
 import { ToolBarConfig } from '@/components/grid/Types';
 import CustomToolBar from '@/components/grid/ToolBar';
+import CompactDialog from '@/pages/dialogs/CompactDialog';
 import { getQueryStyles } from '../query/Styles';
 import { Segment } from './Types';
 
@@ -13,7 +15,9 @@ const Segments: FC<{
   collectionName: string;
 }> = ({ collectionName }) => {
   const classes = getQueryStyles();
-  const [segments, setSegements] = useState<Segment[]>([]);
+  const { setDialog } = useContext(rootContext);
+
+  const [segments, setSegments] = useState<Segment[]>([]);
   const { t: collectionTrans } = useTranslation('collection');
   const [loading, setLoading] = useState<boolean>(true);
 
@@ -35,10 +39,14 @@ const Segments: FC<{
       };
     });
 
-    setSegements(combinedArray);
+    setSegments(combinedArray);
     setLoading(false);
   };
 
+  const onCompactExecuted = async () => {
+    await fetchSegments();
+  };
+
   const toolbarConfigs: ToolBarConfig[] = [
     {
       type: 'iconBtn',
@@ -48,6 +56,25 @@ const Segments: FC<{
       label: collectionTrans('refresh'),
       icon: 'refresh',
     },
+    {
+      type: 'iconBtn',
+      onClick: () => {
+        setDialog({
+          open: true,
+          type: 'custom',
+          params: {
+            component: (
+              <CompactDialog
+                collectionName={collectionName}
+                cb={onCompactExecuted}
+              />
+            ),
+          },
+        });
+      },
+      label: collectionTrans('compact'),
+      icon: 'compact',
+    },
   ];
 
   const colDefinitions: ColDefinitionsType[] = [