Browse Source

better search page (#142)

ryjiang 2 years ago
parent
commit
ce72c115b0

+ 2 - 1
client/src/i18n/cn/button.ts

@@ -21,7 +21,8 @@ const btnTrans = {
   query: 'Query',
   query: 'Query',
   importSampleData: 'Import Sample data',
   importSampleData: 'Import Sample data',
   loading: 'Loading...',
   loading: 'Loading...',
-  importing: 'Importing...'
+  importing: 'Importing...',
+  example: 'Example',
 };
 };
 
 
 export default btnTrans;
 export default btnTrans;

+ 1 - 1
client/src/i18n/cn/search.ts

@@ -1,5 +1,5 @@
 const searchTrans = {
 const searchTrans = {
-  firstTip: '1. Enter vector value {{dimensionTip}}',
+  firstTip: '1. Enter search vector {{dimensionTip}}',
   secondTip: '2. Choose collection and field',
   secondTip: '2. Choose collection and field',
   thirdTip: '3. Set search parameters',
   thirdTip: '3. Set search parameters',
   vectorPlaceholder: 'Please input your vector value here, e.g. [1, 2, 3, 4]',
   vectorPlaceholder: 'Please input your vector value here, e.g. [1, 2, 3, 4]',

+ 2 - 1
client/src/i18n/en/button.ts

@@ -21,7 +21,8 @@ const btnTrans = {
   query: 'Query',
   query: 'Query',
   importSampleData: 'Import Sample data',
   importSampleData: 'Import Sample data',
   loading: 'Loading...',
   loading: 'Loading...',
-  importing: 'Importing...'
+  importing: 'Importing...',
+  example: 'Example',
 };
 };
 
 
 export default btnTrans;
 export default btnTrans;

+ 2 - 2
client/src/i18n/en/search.ts

@@ -1,6 +1,6 @@
 const searchTrans = {
 const searchTrans = {
-  firstTip: '1. Enter vector value {{dimensionTip}}',
-  secondTip: '2. Choose collection and field',
+  firstTip: '2. Enter search vector {{dimensionTip}}',
+  secondTip: '1. Choose collection and field',
   thirdTip: '3. Set search parameters',
   thirdTip: '3. Set search parameters',
   vectorPlaceholder: 'Please input your vector value here, e.g. [1, 2, 3, 4]',
   vectorPlaceholder: 'Please input your vector value here, e.g. [1, 2, 3, 4]',
   collection: 'Choose Collection',
   collection: 'Choose Collection',

+ 2 - 3
client/src/pages/search/SearchParams.tsx

@@ -20,13 +20,12 @@ import { SearchParamInputConfig, SearchParamsProps } from './Types';
 const getStyles = makeStyles((theme: Theme) => ({
 const getStyles = makeStyles((theme: Theme) => ({
   selector: {
   selector: {
     width: '100%',
     width: '100%',
-    marginTop: theme.spacing(2),
+    marginBottom: theme.spacing(2),
   },
   },
   input: {
   input: {
-    marginTop: theme.spacing(2),
+    marginBottom: theme.spacing(2),
   },
   },
   inlineInput: {
   inlineInput: {
-    marginTop: theme.spacing(2),
     width: '48%',
     width: '48%',
   },
   },
   inlineInputWrapper: {
   inlineInputWrapper: {

+ 16 - 9
client/src/pages/search/Styles.ts

@@ -8,9 +8,8 @@ export const getVectorSearchStyles = makeStyles((theme: Theme) => ({
     '& .field': {
     '& .field': {
       display: 'flex',
       display: 'flex',
       flexDirection: 'column',
       flexDirection: 'column',
-      flexBasis: '33%',
-
-      padding: theme.spacing(2, 3, 4),
+      width: 250,
+      padding: theme.spacing(2),
       backgroundColor: '#fff',
       backgroundColor: '#fff',
       borderRadius: theme.spacing(0.5),
       borderRadius: theme.spacing(0.5),
       boxShadow: '3px 3px 10px rgba(0, 0, 0, 0.05)',
       boxShadow: '3px 3px 10px rgba(0, 0, 0, 0.05)',
@@ -18,17 +17,16 @@ export const getVectorSearchStyles = makeStyles((theme: Theme) => ({
       '& .textarea': {
       '& .textarea': {
         border: `1px solid ${theme.palette.attuGrey.main}`,
         border: `1px solid ${theme.palette.attuGrey.main}`,
         borderRadius: theme.spacing(0.5),
         borderRadius: theme.spacing(0.5),
-        padding: theme.spacing(1),
-        paddingBottom: '18px',
-        marginTop: theme.spacing(2),
+        padding: theme.spacing(0, 1),
+        marginBottom: theme.spacing(0.5),
       },
       },
 
 
       // reset default style
       // reset default style
       '& .textfield': {
       '& .textfield': {
-        padding: 0,
         fontSize: '14px',
         fontSize: '14px',
         lineHeight: '20px',
         lineHeight: '20px',
         fontWeight: 400,
         fontWeight: 400,
+        height: '128px',
 
 
         '&::before': {
         '&::before': {
           borderBottom: 'none',
           borderBottom: 'none',
@@ -61,6 +59,7 @@ export const getVectorSearchStyles = makeStyles((theme: Theme) => ({
 
 
     '& .field-second': {
     '& .field-second': {
       flexGrow: 1,
       flexGrow: 1,
+      flexBasis: '50%',
       margin: theme.spacing(0, 1),
       margin: theme.spacing(0, 1),
     },
     },
 
 
@@ -68,16 +67,25 @@ export const getVectorSearchStyles = makeStyles((theme: Theme) => ({
     // if still set padding-bottom, the whole form space will be stretched
     // if still set padding-bottom, the whole form space will be stretched
     '& .field-params': {
     '& .field-params': {
       paddingBottom: 0,
       paddingBottom: 0,
+      width: 390,
     },
     },
 
 
     '& .text': {
     '& .text': {
       color: theme.palette.attuGrey.dark,
       color: theme.palette.attuGrey.dark,
       fontWeight: 500,
       fontWeight: 500,
+      marginBottom: theme.spacing(1),
+      height: theme.spacing(4),
+      '& button': {
+        marginLeft: '8px',
+        position: 'relative',
+        top: -5,
+        verticalAlign: 'top',
+      },
     },
     },
   },
   },
   selector: {
   selector: {
     width: '100%',
     width: '100%',
-    marginTop: theme.spacing(2),
+    marginBottom: theme.spacing(2),
   },
   },
   paramsWrapper: {
   paramsWrapper: {
     display: 'flex',
     display: 'flex',
@@ -123,7 +131,6 @@ export const getVectorSearchStyles = makeStyles((theme: Theme) => ({
     color: theme.palette.attuGrey.dark,
     color: theme.palette.attuGrey.dark,
   },
   },
   error: {
   error: {
-    marginTop: theme.spacing(1),
     color: theme.palette.error.main,
     color: theme.palette.error.main,
   },
   },
 }));
 }));

+ 65 - 41
client/src/pages/search/VectorSearch.tsx

@@ -1,4 +1,4 @@
-import { TextField, Typography } 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 { useNavigationHook } from '../../hooks/Navigation';
 import { ALL_ROUTER_TYPES } from '../../router/Types';
 import { ALL_ROUTER_TYPES } from '../../router/Types';
@@ -33,7 +33,7 @@ import Filter from '../../components/advancedSearch';
 import { Field } from '../../components/advancedSearch/Types';
 import { Field } from '../../components/advancedSearch/Types';
 import { useLocation } from 'react-router-dom';
 import { useLocation } from 'react-router-dom';
 import { parseLocationSearch } from '../../utils/Format';
 import { parseLocationSearch } from '../../utils/Format';
-import { cloneObj } from '../../utils/Common';
+import { cloneObj, generateVector } from '../../utils/Common';
 import { CustomDatePicker } from '../../components/customDatePicker/CustomDatePicker';
 import { CustomDatePicker } from '../../components/customDatePicker/CustomDatePicker';
 import { useTimeTravelHook } from '../../hooks/TimeTravel';
 import { useTimeTravelHook } from '../../hooks/TimeTravel';
 
 
@@ -135,8 +135,10 @@ const VectorSearch = () => {
           }))
           }))
       : [];
       : [];
   }, [searchResult, primaryKeyField]);
   }, [searchResult, primaryKeyField]);
+
+  const [selectedMetricType, setSelectedMetricType] = useState<string>('');
+
   const {
   const {
-    metricType,
     indexType,
     indexType,
     indexParams,
     indexParams,
     fieldType,
     fieldType,
@@ -154,6 +156,8 @@ const VectorSearch = () => {
         index?._metricType || DEFAULT_METRIC_VALUE_MAP[embeddingType];
         index?._metricType || DEFAULT_METRIC_VALUE_MAP[embeddingType];
       const indexParams = index?._indexParameterPairs || [];
       const indexParams = index?._indexParameterPairs || [];
       const dim = selectedFieldInfo?.dimension || 0;
       const dim = selectedFieldInfo?.dimension || 0;
+      setSelectedMetricType(metric);
+
       return {
       return {
         metricType: metric,
         metricType: metric,
         indexType: index?._indexType || getDefaultIndexType(embeddingType),
         indexType: index?._indexType || getDefaultIndexType(embeddingType),
@@ -163,8 +167,8 @@ const VectorSearch = () => {
         selectedFieldDimension: dim,
         selectedFieldDimension: dim,
       };
       };
     }
     }
+
     return {
     return {
-      metricType: '',
       indexType: '',
       indexType: '',
       indexParams: [],
       indexParams: [],
       fieldType: 0,
       fieldType: 0,
@@ -172,8 +176,6 @@ const VectorSearch = () => {
       selectedFieldDimension: 0,
       selectedFieldDimension: 0,
     };
     };
   }, [selectedField, fieldOptions]);
   }, [selectedField, fieldOptions]);
-  const [selectedMetricType, setSelectedMetricType] =
-    useState<string>(metricType);
 
 
   /**
   /**
    * vector value validation
    * vector value validation
@@ -341,15 +343,55 @@ const VectorSearch = () => {
     setVectors(value);
     setVectors(value);
   };
   };
 
 
+  const fillWithExampleVector = (selectedFieldDimension: number) => {
+    const v = generateVector(selectedFieldDimension);
+    setVectors(`[${v}]`);
+  };
+
   return (
   return (
     <section className="page-wrapper">
     <section className="page-wrapper">
       {/* form section */}
       {/* form section */}
       <form className={classes.form}>
       <form className={classes.form}>
+        {/* collection and field selectors */}
+        <fieldset className="field">
+          <Typography className="text">{searchTrans('secondTip')}</Typography>
+          <CustomSelector
+            options={collectionOptions}
+            wrapperClass={classes.selector}
+            variant="filled"
+            label={searchTrans(
+              collectionOptions.length === 0 ? 'noCollection' : 'collection'
+            )}
+            disabled={collectionOptions.length === 0}
+            value={selectedCollection}
+            onChange={(e: { target: { value: unknown } }) => {
+              const collection = e.target.value;
+
+              setSelectedCollection(collection as string);
+              // every time selected collection changed, reset field
+              setSelectedField('');
+              setSearchResult([]);
+            }}
+          />
+          <CustomSelector
+            options={fieldOptions}
+            // readOnly can't avoid all events, so we use disabled instead
+            disabled={selectedCollection === ''}
+            wrapperClass={classes.selector}
+            variant="filled"
+            label={searchTrans('field')}
+            value={selectedField}
+            onChange={(e: { target: { value: unknown } }) => {
+              const field = e.target.value;
+              setSelectedField(field as string);
+            }}
+          />
+        </fieldset>
         {/**
         {/**
          * vector value textarea
          * vector value textarea
          * use field-params class because it also has error msg if invalid
          * use field-params class because it also has error msg if invalid
          */}
          */}
-        <fieldset className="field field-params">
+        <fieldset className="field field-params field-second">
           <Typography className="text">
           <Typography className="text">
             {searchTrans('firstTip', {
             {searchTrans('firstTip', {
               dimensionTip:
               dimensionTip:
@@ -357,7 +399,23 @@ const VectorSearch = () => {
                   ? `(dimension: ${selectedFieldDimension})`
                   ? `(dimension: ${selectedFieldDimension})`
                   : '',
                   : '',
             })}
             })}
+            {selectedFieldDimension !== 0 ? (
+              <Button
+                variant="outlined"
+                size="small"
+                onClick={() => {
+                  const dim =
+                    fieldType === DataTypeEnum.BinaryVector
+                      ? selectedFieldDimension / 8
+                      : selectedFieldDimension;
+                  fillWithExampleVector(dim);
+                }}
+              >
+                {btnTrans('example')}
+              </Button>
+            ) : null}
           </Typography>
           </Typography>
+
           <TextField
           <TextField
             className="textarea"
             className="textarea"
             InputProps={{
             InputProps={{
@@ -386,41 +444,7 @@ const VectorSearch = () => {
             </Typography>
             </Typography>
           )}
           )}
         </fieldset>
         </fieldset>
-        {/* collection and field selectors */}
-        <fieldset className="field field-second">
-          <Typography className="text">{searchTrans('secondTip')}</Typography>
-          <CustomSelector
-            options={collectionOptions}
-            wrapperClass={classes.selector}
-            variant="filled"
-            label={searchTrans(
-              collectionOptions.length === 0 ? 'noCollection' : 'collection'
-            )}
-            disabled={collectionOptions.length === 0}
-            value={selectedCollection}
-            onChange={(e: { target: { value: unknown } }) => {
-              const collection = e.target.value;
 
 
-              setSelectedCollection(collection as string);
-              // every time selected collection changed, reset field
-              setSelectedField('');
-              setSearchResult([]);
-            }}
-          />
-          <CustomSelector
-            options={fieldOptions}
-            // readOnly can't avoid all events, so we use disabled instead
-            disabled={selectedCollection === ''}
-            wrapperClass={classes.selector}
-            variant="filled"
-            label={searchTrans('field')}
-            value={selectedField}
-            onChange={(e: { target: { value: unknown } }) => {
-              const field = e.target.value;
-              setSelectedField(field as string);
-            }}
-          />
-        </fieldset>
         {/* search params selectors */}
         {/* search params selectors */}
         <fieldset className="field field-params">
         <fieldset className="field field-params">
           <Typography className="text">{searchTrans('thirdTip')}</Typography>
           <Typography className="text">{searchTrans('thirdTip')}</Typography>