diff --git a/client/src/http/Collection.ts b/client/src/http/Collection.ts
index 1633d8aa..50bdb916 100644
--- a/client/src/http/Collection.ts
+++ b/client/src/http/Collection.ts
@@ -97,6 +97,20 @@ export class CollectionHttp extends BaseModel implements CollectionView {
return super.search({ path: this.COLLECTIONS_STATISTICS_URL, params: {} });
}
+ static getPSegments(collectionName: string) {
+ return super.search({
+ path: `${this.COLLECTIONS_URL}/${collectionName}/psegments`,
+ params: {},
+ });
+ }
+
+ static getQSegments(collectionName: string) {
+ return super.search({
+ path: `${this.COLLECTIONS_URL}/${collectionName}/qsegments`,
+ params: {},
+ });
+ }
+
static insertData(collectionName: string, param: InsertDataParam) {
return super.create({
path: `${this.COLLECTIONS_URL}/${collectionName}/insert`,
diff --git a/client/src/i18n/en/collection.ts b/client/src/i18n/en/collection.ts
index 2001d452..1f938303 100644
--- a/client/src/i18n/en/collection.ts
+++ b/client/src/i18n/en/collection.ts
@@ -89,6 +89,7 @@ const collectionTrans = {
schemaTab: 'Schema',
queryTab: 'Data Query',
previewTab: 'Data Preview',
+ segmentsTab: 'Segments',
startTip: 'Start your data query',
dataQuerylimits:
' Please note that the maximum number of results for your data query is 16384.',
@@ -100,6 +101,18 @@ const collectionTrans = {
// rename dialog
newColNamePlaceholder: 'New Collection Name',
newNameInfo: 'Only numbers, letters, and underscores are allowed.',
+
+ // segement
+ segements: 'Segments',
+ segPState: 'Persistent Segment State',
+ partitionID: 'Partition ID',
+ segmentID: 'Segment ID',
+ num_rows: 'Row Count',
+ q_nodeIds: 'Query Node IDs',
+ q_index_name: 'Index Name',
+ q_indexID: 'Index ID',
+ q_state: 'Query Segment State',
+ q_mem_size: 'Memory Size',
};
export default collectionTrans;
diff --git a/client/src/pages/collections/Collection.tsx b/client/src/pages/collections/Collection.tsx
index 08c30216..03991b61 100644
--- a/client/src/pages/collections/Collection.tsx
+++ b/client/src/pages/collections/Collection.tsx
@@ -12,6 +12,8 @@ import { parseLocationSearch } from '@/utils';
import Schema from '../schema/Schema';
import Query from '../query/Query';
import Preview from '../preview/Preview';
+import Segments from '../segments/Segments';
+
import { TAB_ENUM } from './Types';
const useStyles = makeStyles((theme: Theme) => ({
@@ -77,6 +79,10 @@ const Collection = () => {
label: collectionTrans('queryTab'),
component: ,
},
+ {
+ label: collectionTrans('segmentsTab'),
+ component: ,
+ },
];
// exclude parititon on cloud
diff --git a/client/src/pages/segments/Segments.tsx b/client/src/pages/segments/Segments.tsx
new file mode 100644
index 00000000..610bd434
--- /dev/null
+++ b/client/src/pages/segments/Segments.tsx
@@ -0,0 +1,143 @@
+import { useEffect, useState, FC } from 'react';
+import { useTranslation } from 'react-i18next';
+import { CollectionHttp } from '@/http';
+import { usePaginationHook } from '@/hooks';
+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 { getQueryStyles } from '../query/Styles';
+import { Segment } from './Types';
+
+const Segments: FC<{
+ collectionName: string;
+}> = ({ collectionName }) => {
+ const classes = getQueryStyles();
+ const [segments, setSegements] = useState([]);
+ const { t: collectionTrans } = useTranslation('collection');
+ const [loading, setLoading] = useState(true);
+
+ const fetchSegments = async () => {
+ setLoading(true);
+
+ const psegments = await CollectionHttp.getPSegments(collectionName);
+ const qsegments = await CollectionHttp.getQSegments(collectionName);
+
+ const combinedArray = psegments.infos.map((p: any) => {
+ const q = qsegments.infos.find((q: any) => q.segmentID === p.segmentID);
+ return {
+ ...p,
+ ...(q &&
+ Object.keys(q).reduce((acc: any, key) => {
+ acc[`q_${key}`] = q[key];
+ return acc;
+ }, {})),
+ };
+ });
+
+ setSegements(combinedArray);
+ setLoading(false);
+ };
+
+ const toolbarConfigs: ToolBarConfig[] = [
+ {
+ type: 'iconBtn',
+ onClick: () => {
+ fetchSegments();
+ },
+ label: collectionTrans('refresh'),
+ icon: 'refresh',
+ },
+ ];
+
+ const colDefinitions: ColDefinitionsType[] = [
+ {
+ id: 'segmentID',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('segmentID'),
+ },
+ {
+ id: 'partitionID',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('partitionID'),
+ },
+ {
+ id: 'state',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('segPState'),
+ },
+ {
+ id: 'num_rows',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('num_rows'),
+ },
+ {
+ id: 'q_nodeIds',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('q_nodeIds'),
+ },
+ {
+ id: 'q_state',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('q_state'),
+ },
+ {
+ id: 'q_index_name',
+ align: 'left',
+ disablePadding: false,
+ label: collectionTrans('q_index_name'),
+ },
+ ];
+
+ useEffect(() => {
+ fetchSegments();
+ }, []);
+
+ const {
+ pageSize,
+ handlePageSize,
+ currentPage,
+ handleCurrentPage,
+ total,
+ data,
+ order,
+ orderBy,
+ handleGridSort,
+ } = usePaginationHook(segments);
+
+ const handlePageChange = (e: any, page: number) => {
+ handleCurrentPage(page);
+ };
+
+ return (
+
+ );
+};
+
+export default Segments;
diff --git a/client/src/pages/segments/Types.ts b/client/src/pages/segments/Types.ts
new file mode 100644
index 00000000..573bb4f4
--- /dev/null
+++ b/client/src/pages/segments/Types.ts
@@ -0,0 +1,17 @@
+export type Segment = {
+ collectionID: string;
+ num_rows: string;
+ partitionID: string;
+ q_collectionID: string;
+ q_indexID: string;
+ q_index_name: string;
+ q_mem_size: string;
+ q_nodeID: string;
+ q_nodeIds: string[];
+ q_num_rows: string;
+ q_partitionID: string;
+ q_segmentID: string;
+ q_state: string;
+ segmentID: string;
+ state: string;
+};
diff --git a/server/src/collections/collections.controller.ts b/server/src/collections/collections.controller.ts
index 8e5fe43b..78341b2a 100644
--- a/server/src/collections/collections.controller.ts
+++ b/server/src/collections/collections.controller.ts
@@ -51,6 +51,8 @@ export class CollectionController {
);
this.router.delete('/:name/alias/:alias', this.dropAlias.bind(this));
this.router.get('/:name', this.describeCollection.bind(this));
+
+ // load / release
this.router.put('/:name/load', this.loadCollection.bind(this));
this.router.put('/:name/release', this.releaseCollection.bind(this));
this.router.post(
@@ -81,6 +83,10 @@ export class CollectionController {
this.createAlias.bind(this)
);
+ // segements
+ this.router.get('/:name/psegments', this.getPSegement.bind(this));
+ this.router.get('/:name/qsegments', this.getQSegement.bind(this));
+
return this.router;
}
@@ -327,4 +333,28 @@ export class CollectionController {
next(error);
}
}
+
+ async getPSegement(req: Request, res: Response, next: NextFunction) {
+ const name = req.params?.name;
+ try {
+ const result = await this.collectionsService.getPersistentSegmentInfo({
+ collectionName: name,
+ });
+ res.send(result);
+ } catch (error) {
+ next(error);
+ }
+ }
+
+ async getQSegement(req: Request, res: Response, next: NextFunction) {
+ const name = req.params?.name;
+ try {
+ const result = await this.collectionsService.getQuerySegmentInfo({
+ collectionName: name,
+ });
+ res.send(result);
+ } catch (error) {
+ next(error);
+ }
+ }
}
diff --git a/server/src/collections/collections.service.ts b/server/src/collections/collections.service.ts
index 863a2878..eb136978 100644
--- a/server/src/collections/collections.service.ts
+++ b/server/src/collections/collections.service.ts
@@ -16,6 +16,9 @@ import {
ShowCollectionsReq,
ShowCollectionsType,
DeleteEntitiesReq,
+ GetCompactionStateReq,
+ GetQuerySegmentInfoReq,
+ GePersistentSegmentInfoReq,
} from '@zilliz/milvus2-sdk-node';
import { throwErrorFromSDK } from '../utils/Error';
import { findKeyValue, genRows } from '../utils/Helper';
@@ -290,4 +293,22 @@ export class CollectionsService {
return await this.insert({ collection_name, fields_data });
}
+
+ async getCompactionState(data: GetCompactionStateReq) {
+ const res = await this.milvusService.client.getCompactionState(data);
+ throwErrorFromSDK(res.status);
+ return res;
+ }
+
+ async getQuerySegmentInfo(data: GetQuerySegmentInfoReq) {
+ const res = await this.milvusService.client.getQuerySegmentInfo(data);
+ throwErrorFromSDK(res.status);
+ return res;
+ }
+
+ async getPersistentSegmentInfo(data: GePersistentSegmentInfoReq) {
+ const res = await this.milvusService.client.getPersistentSegmentInfo(data);
+ throwErrorFromSDK(res.status);
+ return res;
+ }
}