Browse Source

update overview/collection/search after changing database

Signed-off-by: ruiyi.jiang <ruiyi.jiang@zilliz.com>
ruiyi.jiang 1 year ago
parent
commit
bb93fb95b1

+ 7 - 2
client/src/components/layout/Header.tsx

@@ -1,4 +1,4 @@
-import { FC, useContext } from 'react';
+import { FC, useContext, useEffect } from 'react';
 import { makeStyles, Theme, createStyles, Typography } from '@material-ui/core';
 import { makeStyles, Theme, createStyles, Typography } from '@material-ui/core';
 import { useNavigate } from 'react-router-dom';
 import { useNavigate } from 'react-router-dom';
 import { navContext } from '@/context/Navigation';
 import { navContext } from '@/context/Navigation';
@@ -90,6 +90,10 @@ const Header: FC<HeaderType> = props => {
     // navigate(0);
     // navigate(0);
   };
   };
 
 
+  const useDatabase = async (database: string) => {
+    await MilvusHttp.useDatabase({ database });
+  };
+
   const dbOptions = databases.map(d => ({ value: d, label: d }));
   const dbOptions = databases.map(d => ({ value: d, label: d }));
 
 
   return (
   return (
@@ -106,8 +110,9 @@ const Header: FC<HeaderType> = props => {
             <CustomSelector
             <CustomSelector
               label="Database"
               label="Database"
               value={database}
               value={database}
-              onChange={(e: { target: { value: unknown } }) => {
+              onChange={async (e: { target: { value: unknown } }) => {
                 const database = e.target.value as string;
                 const database = e.target.value as string;
+                await useDatabase(database);
                 setDatabase(database);
                 setDatabase(database);
               }}
               }}
               options={dbOptions}
               options={dbOptions}

+ 1 - 1
client/src/hooks/Navigation.ts

@@ -22,7 +22,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('overview'),
           navTitle: navTrans('overview'),
           backPath: '',
           backPath: '',
-          showDatabaseSelector: false,
+          showDatabaseSelector: true,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;

+ 5 - 1
client/src/http/Milvus.ts

@@ -8,7 +8,7 @@ export class MilvusHttp extends BaseModel {
   static FLUSH_URL = '/milvus/flush';
   static FLUSH_URL = '/milvus/flush';
   static METRICS_URL = '/milvus/metrics';
   static METRICS_URL = '/milvus/metrics';
   static VERSION_URL = '/milvus/version';
   static VERSION_URL = '/milvus/version';
-
+  static USE_DB_URL = '/milvus/usedb';
   static TIGGER_CRON_URL = '/crons';
   static TIGGER_CRON_URL = '/crons';
 
 
   constructor(props: {}) {
   constructor(props: {}) {
@@ -58,4 +58,8 @@ export class MilvusHttp extends BaseModel {
       data,
       data,
     });
     });
   }
   }
+
+  static useDatabase(data: { database: string }) {
+    return super.create({ path: this.USE_DB_URL, data });
+  }
 }
 }

+ 5 - 3
client/src/pages/collections/Collections.tsx

@@ -3,6 +3,7 @@ import { Link, useSearchParams } from 'react-router-dom';
 import { makeStyles, Theme } from '@material-ui/core';
 import { makeStyles, Theme } from '@material-ui/core';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 import { authContext } from '@/context/Auth';
 import { authContext } from '@/context/Auth';
+import { databaseContext } from '@/context/Database';
 import { useNavigationHook } from '@/hooks/Navigation';
 import { useNavigationHook } from '@/hooks/Navigation';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
 import AttuGrid from '@/components/grid/Grid';
 import AttuGrid from '@/components/grid/Grid';
@@ -27,9 +28,9 @@ import Highlighter from 'react-highlight-words';
 import InsertDialog from '../dialogs/insert/Dialog';
 import InsertDialog from '../dialogs/insert/Dialog';
 import ImportSampleDialog from '../dialogs/ImportSampleDialog';
 import ImportSampleDialog from '../dialogs/ImportSampleDialog';
 import { MilvusHttp } from '@/http/Milvus';
 import { MilvusHttp } from '@/http/Milvus';
-import { LOADING_STATE } from '../../consts/Milvus';
+import { LOADING_STATE } from '@/consts/Milvus';
 import { webSocketContext } from '@/context/WebSocket';
 import { webSocketContext } from '@/context/WebSocket';
-import { WS_EVENTS, WS_EVENTS_TYPE } from '../../consts/Http';
+import { WS_EVENTS, WS_EVENTS_TYPE } from '@/consts/Http';
 import { checkIndexBuilding, checkLoading } from '@/utils/Validation';
 import { checkIndexBuilding, checkLoading } from '@/utils/Validation';
 import Aliases from './Aliases';
 import Aliases from './Aliases';
 
 
@@ -59,6 +60,7 @@ const useStyles = makeStyles((theme: Theme) => ({
 const Collections = () => {
 const Collections = () => {
   useNavigationHook(ALL_ROUTER_TYPES.COLLECTIONS);
   useNavigationHook(ALL_ROUTER_TYPES.COLLECTIONS);
   const { isManaged } = useContext(authContext);
   const { isManaged } = useContext(authContext);
+  const { database } = useContext(databaseContext);
 
 
   const [searchParams] = useSearchParams();
   const [searchParams] = useSearchParams();
   const [search, setSearch] = useState<string>(
   const [search, setSearch] = useState<string>(
@@ -105,7 +107,7 @@ const Collections = () => {
 
 
   useEffect(() => {
   useEffect(() => {
     fetchData();
     fetchData();
-  }, [fetchData]);
+  }, [fetchData, database]);
 
 
   const formatCollections = useMemo(() => {
   const formatCollections = useMemo(() => {
     const filteredCollections = search
     const filteredCollections = search

+ 25 - 18
client/src/pages/search/VectorSearch.tsx

@@ -1,24 +1,26 @@
+import { useCallback, useEffect, useMemo, useState, useContext } from 'react';
 import { TextField, Typography, Button } from '@material-ui/core';
 import { TextField, Typography, Button } from '@material-ui/core';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
-import { useNavigationHook } from '@/hooks/Navigation';
+import { useLocation } from 'react-router-dom';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
+import { useNavigationHook } from '@/hooks/Navigation';
+import { useSearchResult } from '@/hooks/Result';
+import { usePaginationHook } from '@/hooks/Pagination';
+import { useTimeTravelHook } from '@/hooks/TimeTravel';
+import { databaseContext } from '@/context/Database';
 import CustomSelector from '@/components/customSelector/CustomSelector';
 import CustomSelector from '@/components/customSelector/CustomSelector';
-import { useCallback, useEffect, useMemo, useState } from 'react';
-import SearchParams from './SearchParams';
-import { DEFAULT_METRIC_VALUE_MAP } from '../../consts/Milvus';
-import { FieldOption, SearchResultView, VectorSearchParam } from './Types';
+import { ColDefinitionsType } from '@/components/grid/Types';
 import AttuGrid from '@/components/grid/Grid';
 import AttuGrid from '@/components/grid/Grid';
 import EmptyCard from '@/components/cards/EmptyCard';
 import EmptyCard from '@/components/cards/EmptyCard';
 import icons from '@/components/icons/Icons';
 import icons from '@/components/icons/Icons';
-import { usePaginationHook } from '@/hooks/Pagination';
 import CustomButton from '@/components/customButton/CustomButton';
 import CustomButton from '@/components/customButton/CustomButton';
 import SimpleMenu from '@/components/menu/SimpleMenu';
 import SimpleMenu from '@/components/menu/SimpleMenu';
-import { TOP_K_OPTIONS } from './Constants';
 import { Option } from '@/components/customSelector/Types';
 import { Option } from '@/components/customSelector/Types';
+import Filter from '@/components/advancedSearch';
+import { Field } from '@/components/advancedSearch/Types';
+import { CustomDatePicker } from '@/components/customDatePicker/CustomDatePicker';
 import { CollectionHttp } from '@/http/Collection';
 import { CollectionHttp } from '@/http/Collection';
-import { CollectionData, DataTypeEnum } from '../collections/Types';
 import { IndexHttp } from '@/http/Index';
 import { IndexHttp } from '@/http/Index';
-import { getVectorSearchStyles } from './Styles';
 import { parseValue } from '@/utils/Insert';
 import { parseValue } from '@/utils/Insert';
 import {
 import {
   classifyFields,
   classifyFields,
@@ -27,21 +29,21 @@ import {
   getNonVectorFieldsForFilter,
   getNonVectorFieldsForFilter,
   getVectorFieldOptions,
   getVectorFieldOptions,
 } from '@/utils/search';
 } from '@/utils/search';
-import { ColDefinitionsType } from '@/components/grid/Types';
-import Filter from '@/components/advancedSearch';
-import { Field } from '@/components/advancedSearch/Types';
-import { useLocation } from 'react-router-dom';
 import { parseLocationSearch } from '@/utils/Format';
 import { parseLocationSearch } from '@/utils/Format';
 import { cloneObj, generateVector } from '@/utils/Common';
 import { cloneObj, generateVector } from '@/utils/Common';
-import { CustomDatePicker } from '@/components/customDatePicker/CustomDatePicker';
-import { useTimeTravelHook } from '@/hooks/TimeTravel';
 import { LOADING_STATE } from '@/consts/Milvus';
 import { LOADING_STATE } from '@/consts/Milvus';
+import { DEFAULT_METRIC_VALUE_MAP } from '@/consts/Milvus';
 import { getLabelDisplayedRows } from './Utils';
 import { getLabelDisplayedRows } from './Utils';
-import { useSearchResult } from '@/hooks/Result';
+import SearchParams from './SearchParams';
+import { getVectorSearchStyles } from './Styles';
+import { CollectionData, DataTypeEnum } from '../collections/Types';
+import { TOP_K_OPTIONS } from './Constants';
+import { FieldOption, SearchResultView, VectorSearchParam } from './Types';
 
 
 const VectorSearch = () => {
 const VectorSearch = () => {
   useNavigationHook(ALL_ROUTER_TYPES.SEARCH);
   useNavigationHook(ALL_ROUTER_TYPES.SEARCH);
   const location = useLocation();
   const location = useLocation();
+  const { database } = useContext(databaseContext);
 
 
   // i18n
   // i18n
   const { t: searchTrans } = useTranslation('search');
   const { t: searchTrans } = useTranslation('search');
@@ -237,7 +239,7 @@ const VectorSearch = () => {
   const fetchCollections = useCallback(async () => {
   const fetchCollections = useCallback(async () => {
     const collections = await CollectionHttp.getCollections();
     const collections = await CollectionHttp.getCollections();
     setCollections(collections.filter(c => c._status === LOADING_STATE.LOADED));
     setCollections(collections.filter(c => c._status === LOADING_STATE.LOADED));
-  }, []);
+  }, [database]);
 
 
   const fetchFieldsWithIndex = useCallback(
   const fetchFieldsWithIndex = useCallback(
     async (collectionName: string, collections: CollectionData[]) => {
     async (collectionName: string, collections: CollectionData[]) => {
@@ -260,13 +262,18 @@ const VectorSearch = () => {
       const filterFields = getNonVectorFieldsForFilter(nonVectorFields);
       const filterFields = getNonVectorFieldsForFilter(nonVectorFields);
       setFilterFields(filterFields);
       setFilterFields(filterFields);
     },
     },
-    []
+    [collections]
   );
   );
 
 
   useEffect(() => {
   useEffect(() => {
     fetchCollections();
     fetchCollections();
   }, [fetchCollections]);
   }, [fetchCollections]);
 
 
+  // clear selection if database is changed
+  useEffect(() => {
+    setSelectedCollection('');
+  }, [database]);
+
   // get field options with index when selected collection changed
   // get field options with index when selected collection changed
   useEffect(() => {
   useEffect(() => {
     if (selectedCollection !== '') {
     if (selectedCollection !== '') {

+ 5 - 0
server/src/milvus/dto.ts

@@ -10,6 +10,11 @@ export class CheckMilvusDto {
   readonly address: string;
   readonly address: string;
 }
 }
 
 
+export class UseDatabaseDto {
+  @IsString()
+  readonly database: string;
+}
+
 export class FlushDto {
 export class FlushDto {
   @IsArray()
   @IsArray()
   @ArrayMinSize(1, { message: "At least need one collection name." })
   @ArrayMinSize(1, { message: "At least need one collection name." })

+ 17 - 1
server/src/milvus/milvus.controller.ts

@@ -1,7 +1,7 @@
 import { NextFunction, Request, Response, Router } from 'express';
 import { NextFunction, Request, Response, Router } from 'express';
 import { dtoValidationMiddleware } from '../middlewares/validation';
 import { dtoValidationMiddleware } from '../middlewares/validation';
 import { MilvusService } from './milvus.service';
 import { MilvusService } from './milvus.service';
-import { ConnectMilvusDto, FlushDto } from './dto';
+import { ConnectMilvusDto, FlushDto, UseDatabaseDto } from './dto';
 import { INSIGHT_CACHE } from '../utils/Const';
 import { INSIGHT_CACHE } from '../utils/Const';
 import packageJson from '../../package.json';
 import packageJson from '../../package.json';
 
 
@@ -25,6 +25,11 @@ export class MilvusController {
       dtoValidationMiddleware(ConnectMilvusDto),
       dtoValidationMiddleware(ConnectMilvusDto),
       this.connectMilvus.bind(this)
       this.connectMilvus.bind(this)
     );
     );
+    this.router.post(
+      '/usedb',
+      dtoValidationMiddleware(UseDatabaseDto),
+      this.useDatabase.bind(this)
+    );
     this.router.post('/disconnect', this.closeConnection.bind(this));
     this.router.post('/disconnect', this.closeConnection.bind(this));
     this.router.get('/check', this.checkConnect.bind(this));
     this.router.get('/check', this.checkConnect.bind(this));
     this.router.put(
     this.router.put(
@@ -95,6 +100,17 @@ export class MilvusController {
     res.send(data);
     res.send(data);
   }
   }
 
 
+  async useDatabase(req: Request, res: Response, next: NextFunction) {
+    const { database } = req.body;
+
+    try {
+      const result = await this.milvusService.useDatabase(database);
+      res.send(result);
+    } catch (error) {
+      next(error);
+    }
+  }
+
   closeConnection(req: Request, res: Response, next: NextFunction) {
   closeConnection(req: Request, res: Response, next: NextFunction) {
     const result = this.milvusService.closeConnection();
     const result = this.milvusService.closeConnection();
     res.send({ result });
     res.send({ result });

+ 7 - 0
server/src/milvus/milvus.service.ts

@@ -101,4 +101,11 @@ export class MilvusService {
     const res = MilvusService.activeMilvusClient.closeConnection();
     const res = MilvusService.activeMilvusClient.closeConnection();
     return res;
     return res;
   }
   }
+
+  async useDatabase(db: string) {
+    const res = await MilvusService.activeMilvusClient.use({
+      db_name: db,
+    });
+    return res;
+  }
 }
 }