Browse Source

Merge pull request #241 from zilliztech/database

Support database
ryjiang 1 year ago
parent
commit
8ba124a11c

+ 12 - 9
client/src/App.tsx

@@ -6,20 +6,23 @@ import { NavProvider } from './context/Navigation';
 import { AuthProvider } from './context/Auth';
 import { AuthProvider } from './context/Auth';
 import { WebSocketProvider } from './context/WebSocket';
 import { WebSocketProvider } from './context/WebSocket';
 import { PrometheusProvider } from './context/Prometheus';
 import { PrometheusProvider } from './context/Prometheus';
+import { DatabaseProvider } from './context/Database';
 
 
 function App() {
 function App() {
   return (
   return (
     <AuthProvider>
     <AuthProvider>
       <RootProvider>
       <RootProvider>
-        <PrometheusProvider>
-          <WebSocketProvider>
-            <NavProvider>
-              <MuiPickersUtilsProvider utils={DayjsUtils}>
-                <Router></Router>
-              </MuiPickersUtilsProvider>
-            </NavProvider>
-          </WebSocketProvider>
-        </PrometheusProvider>
+        <DatabaseProvider>
+          <PrometheusProvider>
+            <WebSocketProvider>
+              <NavProvider>
+                <MuiPickersUtilsProvider utils={DayjsUtils}>
+                  <Router></Router>
+                </MuiPickersUtilsProvider>
+              </NavProvider>
+            </WebSocketProvider>
+          </PrometheusProvider>
+        </DatabaseProvider>
       </RootProvider>
       </RootProvider>
     </AuthProvider>
     </AuthProvider>
   );
   );

+ 37 - 8
client/src/components/layout/Header.tsx

@@ -1,13 +1,15 @@
-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 { HeaderType } from './Types';
-import { navContext } from '../../context/Navigation';
-import icons from '../icons/Icons';
 import { useNavigate } from 'react-router-dom';
 import { useNavigate } from 'react-router-dom';
-import { authContext } from '../../context/Auth';
+import { navContext } from '@/context/Navigation';
+import { databaseContext } from '@/context/Database';
+import { authContext } from '@/context/Auth';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
-import { MilvusHttp } from '../../http/Milvus';
-import { MILVUS_ADDRESS } from '../../consts/Localstorage';
+import { MilvusHttp } from '@/http/Milvus';
+import { MILVUS_ADDRESS } from '@/consts/Localstorage';
+import CustomSelector from '@/components/customSelector/CustomSelector';
+import icons from '../icons/Icons';
+import { HeaderType } from './Types';
 
 
 const useStyles = makeStyles((theme: Theme) =>
 const useStyles = makeStyles((theme: Theme) =>
   createStyles({
   createStyles({
@@ -22,7 +24,7 @@ const useStyles = makeStyles((theme: Theme) =>
       justifyContent: 'space-between',
       justifyContent: 'space-between',
       alignItems: 'center',
       alignItems: 'center',
       paddingTop: theme.spacing(3),
       paddingTop: theme.spacing(3),
-      paddingLeft: theme.spacing(5),
+      paddingLeft: theme.spacing(4),
       flex: 1,
       flex: 1,
     },
     },
     navigation: {
     navigation: {
@@ -32,6 +34,7 @@ const useStyles = makeStyles((theme: Theme) =>
     icon: {
     icon: {
       color: theme.palette.primary.main,
       color: theme.palette.primary.main,
       cursor: 'pointer',
       cursor: 'pointer',
+      marginRight: theme.spacing(1),
     },
     },
     addressWrapper: {
     addressWrapper: {
       display: 'flex',
       display: 'flex',
@@ -54,14 +57,20 @@ const useStyles = makeStyles((theme: Theme) =>
         },
         },
       },
       },
     },
     },
+    database: {
+      width: theme.spacing(16),
+      marginRight: theme.spacing(2),
+    },
   })
   })
 );
 );
 
 
 const Header: FC<HeaderType> = props => {
 const Header: FC<HeaderType> = props => {
   const classes = useStyles();
   const classes = useStyles();
   const { navInfo } = useContext(navContext);
   const { navInfo } = useContext(navContext);
+  const { database, databases, setDatabase } = useContext(databaseContext);
   const { address, setAddress, setIsAuth } = useContext(authContext);
   const { address, setAddress, setIsAuth } = useContext(authContext);
   const navigate = useNavigate();
   const navigate = useNavigate();
+
   const { t: commonTrans } = useTranslation();
   const { t: commonTrans } = useTranslation();
   const statusTrans = commonTrans('status');
   const statusTrans = commonTrans('status');
   const BackIcon = icons.back;
   const BackIcon = icons.back;
@@ -80,6 +89,12 @@ 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 }));
+
   return (
   return (
     <header className={classes.header}>
     <header className={classes.header}>
       <div className={classes.contentWrapper}>
       <div className={classes.contentWrapper}>
@@ -90,6 +105,20 @@ const Header: FC<HeaderType> = props => {
               onClick={() => handleBack(navInfo.backPath)}
               onClick={() => handleBack(navInfo.backPath)}
             />
             />
           )}
           )}
+          {navInfo.showDatabaseSelector ? (
+            <CustomSelector
+              label="Database"
+              value={database}
+              onChange={async (e: { target: { value: unknown } }) => {
+                const database = e.target.value as string;
+                await useDatabase(database);
+                setDatabase(database);
+              }}
+              options={dbOptions}
+              variant="filled"
+              wrapperClass={classes.database}
+            />
+          ) : null}
 
 
           <Typography variant="h4" color="textPrimary">
           <Typography variant="h4" color="textPrimary">
             {navInfo.navTitle}
             {navInfo.navTitle}

+ 1 - 1
client/src/components/menu/NavMenu.tsx

@@ -132,7 +132,7 @@ const useStyles = makeStyles((theme: Theme) =>
       },
       },
     },
     },
     expandIcon: {
     expandIcon: {
-      left: '187px',
+      left: '160px',
       transform: 'rotateZ(180deg)',
       transform: 'rotateZ(180deg)',
     },
     },
     collapseIcon: {
     collapseIcon: {

+ 36 - 0
client/src/context/Database.tsx

@@ -0,0 +1,36 @@
+import { createContext, useEffect, useState } from 'react';
+import { DatabaseHttp } from '@/http/Database';
+import { DatabaseContextType } from './Types';
+
+export const databaseContext = createContext<DatabaseContextType>({
+  database: 'default',
+  databases: ['default'],
+  setDatabase: () => {},
+});
+
+const { Provider } = databaseContext;
+export const DatabaseProvider = (props: { children: React.ReactNode }) => {
+  const [database, setDatabase] = useState<string>('default');
+  const [databases, setDatabases] = useState<string[]>(['default']);
+
+  const fetchDatabases = async () => {
+    const res = await DatabaseHttp.getDatabases();
+    setDatabases(res.db_names);
+  };
+
+  useEffect(() => {
+    fetchDatabases();
+  }, []);
+
+  return (
+    <Provider
+      value={{
+        database,
+        databases,
+        setDatabase,
+      }}
+    >
+      {props.children}
+    </Provider>
+  );
+};

+ 3 - 0
client/src/context/Navigation.tsx

@@ -7,6 +7,7 @@ export const navContext = createContext<NavContextType>({
   navInfo: {
   navInfo: {
     navTitle: '',
     navTitle: '',
     backPath: '',
     backPath: '',
+    showDatabaseSelector: false,
   },
   },
   setNavInfo: () => {},
   setNavInfo: () => {},
 });
 });
@@ -15,9 +16,11 @@ const { Provider } = navContext;
 
 
 export const NavProvider = (props: { children: React.ReactNode }) => {
 export const NavProvider = (props: { children: React.ReactNode }) => {
   const { t } = useTranslation('nav');
   const { t } = useTranslation('nav');
+
   const [navInfo, setNavInfo] = useState<NavInfo>({
   const [navInfo, setNavInfo] = useState<NavInfo>({
     navTitle: t('overview'),
     navTitle: t('overview'),
     backPath: '',
     backPath: '',
+    showDatabaseSelector: false,
   });
   });
 
 
   return <Provider value={{ navInfo, setNavInfo }}>{props.children}</Provider>;
   return <Provider value={{ navInfo, setNavInfo }}>{props.children}</Provider>;

+ 6 - 0
client/src/context/Types.ts

@@ -62,6 +62,12 @@ export type AuthContextType = {
   setIsAuth: Dispatch<SetStateAction<boolean>>;
   setIsAuth: Dispatch<SetStateAction<boolean>>;
 };
 };
 
 
+export type DatabaseContextType = {
+  database: string;
+  databases: string[];
+  setDatabase: Dispatch<SetStateAction<string>>;
+};
+
 export type PrometheusContextType = {
 export type PrometheusContextType = {
   withPrometheus: boolean;
   withPrometheus: boolean;
   setWithPrometheus: Dispatch<SetStateAction<boolean>>;
   setWithPrometheus: Dispatch<SetStateAction<boolean>>;

+ 2 - 2
client/src/context/WebSocket.tsx

@@ -9,12 +9,12 @@ import { CollectionView } from '../pages/collections/Types';
 import { checkIndexBuilding, checkLoading } from '../utils/Validation';
 import { checkIndexBuilding, checkLoading } from '../utils/Validation';
 import { WebSocketType } from './Types';
 import { WebSocketType } from './Types';
 
 
-export const webSokcetContext = createContext<WebSocketType>({
+export const webSocketContext = createContext<WebSocketType>({
   collections: [],
   collections: [],
   setCollections: data => {},
   setCollections: data => {},
 });
 });
 
 
-const { Provider } = webSokcetContext;
+const { Provider } = webSocketContext;
 
 
 export const WebSocketProvider = (props: { children: React.ReactNode }) => {
 export const WebSocketProvider = (props: { children: React.ReactNode }) => {
   const [collections, setCollections] = useState<CollectionView[]>([]);
   const [collections, setCollections] = useState<CollectionView[]>([]);

+ 7 - 8
client/src/hooks/Navigation.ts

@@ -22,6 +22,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('overview'),
           navTitle: navTrans('overview'),
           backPath: '',
           backPath: '',
+          showDatabaseSelector: true,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;
@@ -30,6 +31,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('database'),
           navTitle: navTrans('database'),
           backPath: '',
           backPath: '',
+          showDatabaseSelector: false,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;
@@ -38,6 +40,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('collection'),
           navTitle: navTrans('collection'),
           backPath: '',
           backPath: '',
+          showDatabaseSelector: true,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;
@@ -46,6 +49,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: collectionName,
           navTitle: collectionName,
           backPath: '/collections',
           backPath: '/collections',
+          showDatabaseSelector: false,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;
@@ -54,6 +58,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('search'),
           navTitle: navTrans('search'),
           backPath: '',
           backPath: '',
+          showDatabaseSelector: true,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;
@@ -62,6 +67,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('system'),
           navTitle: navTrans('system'),
           backPath: '',
           backPath: '',
+          showDatabaseSelector: false,
         };
         };
         setNavInfo(navInfo);
         setNavInfo(navInfo);
         break;
         break;
@@ -70,14 +76,7 @@ export const useNavigationHook = (
         const navInfo: NavInfo = {
         const navInfo: NavInfo = {
           navTitle: navTrans('user'),
           navTitle: navTrans('user'),
           backPath: '',
           backPath: '',
-        };
-        setNavInfo(navInfo);
-        break;
-      }
-      case ALL_ROUTER_TYPES.PLUGIN: {
-        const navInfo: NavInfo = {
-          navTitle: title,
-          backPath: '',
+          showDatabaseSelector: false,
         };
         };
         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 });
+  }
 }
 }

+ 7 - 5
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 { webSokcetContext } from '@/context/WebSocket';
-import { WS_EVENTS, WS_EVENTS_TYPE } from '../../consts/Http';
+import { LOADING_STATE } from '@/consts/Milvus';
+import { webSocketContext } from '@/context/WebSocket';
+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>(
@@ -70,7 +72,7 @@ const Collections = () => {
   >([]);
   >([]);
 
 
   const { setDialog, openSnackBar } = useContext(rootContext);
   const { setDialog, openSnackBar } = useContext(rootContext);
-  const { collections, setCollections } = useContext(webSokcetContext);
+  const { collections, setCollections } = useContext(webSocketContext);
   const { t: collectionTrans } = useTranslation('collection');
   const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
   const { t: btnTrans } = useTranslation('btn');
   const { t: successTrans } = useTranslation('success');
   const { t: successTrans } = useTranslation('success');
@@ -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

+ 1 - 1
client/src/pages/index.tsx

@@ -130,7 +130,7 @@ function Index() {
         <GlobalEffect>
         <GlobalEffect>
           <div className={classes.content}>
           <div className={classes.content}>
             <NavMenu
             <NavMenu
-              width="200px"
+              width="172px"
               data={menuItems}
               data={menuItems}
               defaultActive={defaultActive}
               defaultActive={defaultActive}
               // used for nested child menu
               // used for nested child menu

+ 7 - 6
client/src/pages/overview/Overview.tsx

@@ -1,19 +1,19 @@
 import { makeStyles, Theme, Typography, useTheme } from '@material-ui/core';
 import { makeStyles, Theme, Typography, useTheme } from '@material-ui/core';
 import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
 import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
+import { databaseContext } from '@/context/Database';
 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 { WS_EVENTS, WS_EVENTS_TYPE } from '../../consts/Http';
-import { LOADING_STATE } from '../../consts/Milvus';
+import { WS_EVENTS, WS_EVENTS_TYPE } from '@/consts/Http';
+import { LOADING_STATE } from '@/consts/Milvus';
 import { rootContext } from '@/context/Root';
 import { rootContext } from '@/context/Root';
-import { webSokcetContext } from '@/context/WebSocket';
+import { webSocketContext } from '@/context/WebSocket';
 import { useNavigationHook } from '@/hooks/Navigation';
 import { useNavigationHook } from '@/hooks/Navigation';
 import { CollectionHttp } from '@/http/Collection';
 import { CollectionHttp } from '@/http/Collection';
 import { MilvusHttp } from '@/http/Milvus';
 import { MilvusHttp } from '@/http/Milvus';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
 import { ALL_ROUTER_TYPES } from '@/router/Types';
 import { formatNumber } from '@/utils/Common';
 import { formatNumber } from '@/utils/Common';
 import { checkLoading, checkIndexBuilding } from '@/utils/Validation';
 import { checkLoading, checkIndexBuilding } from '@/utils/Validation';
-import { CollectionData } from '../collections/Types';
 import CollectionCard from './collectionCard/CollectionCard';
 import CollectionCard from './collectionCard/CollectionCard';
 import StatisticsCard from './statisticsCard/StatisticsCard';
 import StatisticsCard from './statisticsCard/StatisticsCard';
 
 
@@ -33,6 +33,7 @@ const useStyles = makeStyles((theme: Theme) => ({
 
 
 const Overview = () => {
 const Overview = () => {
   useNavigationHook(ALL_ROUTER_TYPES.OVERVIEW);
   useNavigationHook(ALL_ROUTER_TYPES.OVERVIEW);
+  const { database } = useContext(databaseContext);
   const classes = useStyles();
   const classes = useStyles();
   const theme = useTheme();
   const theme = useTheme();
   const { t: overviewTrans } = useTranslation('overview');
   const { t: overviewTrans } = useTranslation('overview');
@@ -46,7 +47,7 @@ const Overview = () => {
     totalData: 0,
     totalData: 0,
   });
   });
   const [loading, setLoading] = useState(false);
   const [loading, setLoading] = useState(false);
-  const { collections, setCollections } = useContext(webSokcetContext);
+  const { collections, setCollections } = useContext(webSocketContext);
   const { openSnackBar } = useContext(rootContext);
   const { openSnackBar } = useContext(rootContext);
 
 
   const fetchData = useCallback(async () => {
   const fetchData = useCallback(async () => {
@@ -66,7 +67,7 @@ const Overview = () => {
     setStatistics(res);
     setStatistics(res);
     setCollections(collections);
     setCollections(collections);
     setLoading(false);
     setLoading(false);
-  }, [setCollections]);
+  }, [setCollections, database]);
 
 
   useEffect(() => {
   useEffect(() => {
     fetchData();
     fetchData();

+ 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 !== '') {

+ 1 - 1
client/src/pages/system/SystemView.tsx

@@ -16,7 +16,7 @@ import { parseJson } from '@/utils/Metric';
 const getStyles = makeStyles((theme: Theme) => ({
 const getStyles = makeStyles((theme: Theme) => ({
   root: {
   root: {
     fontFamily: 'Roboto',
     fontFamily: 'Roboto',
-    margin: '14px 40px',
+    margin: '12px 32px',
     position: 'relative',
     position: 'relative',
     height: 'fit-content',
     height: 'fit-content',
     display: 'flex',
     display: 'flex',

+ 1 - 1
client/src/pages/user/Users.tsx

@@ -1,5 +1,5 @@
 import { useMemo } from 'react';
 import { useMemo } from 'react';
-import { useNavigate, useLocation, useParams } from 'react-router-dom';
+import { useNavigate, useLocation } from 'react-router-dom';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 import { makeStyles, Theme } from '@material-ui/core';
 import { makeStyles, Theme } from '@material-ui/core';
 import { useNavigationHook } from '@/hooks/Navigation';
 import { useNavigationHook } from '@/hooks/Navigation';

+ 1 - 0
client/src/router/Types.ts

@@ -18,4 +18,5 @@ export enum ALL_ROUTER_TYPES {
 export type NavInfo = {
 export type NavInfo = {
   navTitle: string;
   navTitle: string;
   backPath: string;
   backPath: string;
+  showDatabaseSelector: boolean;
 };
 };

+ 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;
+  }
 }
 }