Sfoglia il codice sorgente

refactor scalar index and add bitmap index support (#710)

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 5 mesi fa
parent
commit
b0211c8da2

+ 1 - 1
client/src/components/customInput/Types.ts

@@ -77,7 +77,7 @@ export interface ITextfieldConfig {
   validations?: IValidation[];
   fullWidth?: boolean;
   className?: string;
-  type?: 'text' | 'number' | 'password';
+  type?: 'text' | 'number' | 'password' | 'bool';
   onBlur?: (event: any) => void;
   onChange?: (event: any) => void;
   onKeyDown?: (event: any) => void;

+ 9 - 15
client/src/consts/Milvus.ts

@@ -52,6 +52,7 @@ export enum INDEX_TYPES_ENUM {
   SPARSE_WAND = 'SPARSE_WAND',
   // inverted
   INVERTED = 'INVERTED',
+  BITMAP = 'BITMAP',
 }
 
 export enum METRIC_TYPES_VALUES {
@@ -261,16 +262,6 @@ export const INDEX_OPTIONS_MAP = {
     label: v,
     value: v,
   })),
-  [DataTypeEnum.VarChar]: [
-    {
-      label: 'INVERTED',
-      value: INDEX_TYPES_ENUM.INVERTED,
-    },
-    {
-      label: 'marisa-trie',
-      value: INDEX_TYPES_ENUM.MARISA_TRIE,
-    },
-  ],
   ['DISK']: Object.keys(DISK_INDEX_CONFIG).map(v => ({
     label: v,
     value: v,
@@ -281,6 +272,13 @@ export const INDEX_OPTIONS_MAP = {
   })),
 };
 
+export const SCALAR_INDEX_OPTIONS = [
+  { label: INDEX_TYPES_ENUM.INVERTED, value: INDEX_TYPES_ENUM.INVERTED },
+  { label: INDEX_TYPES_ENUM.SORT, value: INDEX_TYPES_ENUM.SORT },
+  { label: INDEX_TYPES_ENUM.MARISA_TRIE, value: INDEX_TYPES_ENUM.MARISA_TRIE },
+  { label: INDEX_TYPES_ENUM.BITMAP, value: INDEX_TYPES_ENUM.BITMAP },
+];
+
 // search params default value map
 export const DEFAULT_SEARCH_PARAM_VALUE_MAP: {
   [key in searchKeywordsType]?: number;
@@ -395,11 +393,7 @@ export enum DataTypeStringEnum {
   None = 'None',
 }
 
-export const NONE_INDEXABLE_DATA_TYPES = [
-  DataTypeStringEnum.Bool,
-  DataTypeStringEnum.JSON,
-  DataTypeStringEnum.Array,
-];
+export const NONE_INDEXABLE_DATA_TYPES = [DataTypeStringEnum.JSON];
 
 export type Property = { key: string; value: any; desc: string; type: string };
 

+ 4 - 2
client/src/pages/databases/collections/schema/CreateForm.tsx

@@ -56,7 +56,7 @@ const CreateForm = (
       key: string;
       min?: number;
       max?: number;
-      type?: string;
+      type?: 'number' | 'text' | 'password' | 'bool';
     }) => {
       const { label, key, min, max, type = 'number' } = props;
       const config: ITextfieldConfig = {
@@ -220,7 +220,9 @@ const CreateForm = (
           const type = e.target.value;
           updateForm('index_type', type as string);
           // reset metric type value
-          updateForm('metric_type', metricOptions[0].value as string);
+          if (metricOptions[0]) {
+            updateForm('metric_type', metricOptions[0].value as string);
+          }
           indexTypeChange && indexTypeChange(type as string);
         }}
         className={classes.select}

+ 11 - 20
client/src/pages/databases/collections/schema/CreateIndexDialog.tsx

@@ -17,13 +17,14 @@ import { useFormValidation } from '@/hooks';
 import { getCreateIndexJSCode } from '@/utils/code/Js';
 import { getCreateIndexPYCode } from '@/utils/code/Py';
 import { getCreateIndexJavaCode } from '@/utils/code/Java';
-import { formatForm, getMetricOptions } from '@/utils';
+import { formatForm, getMetricOptions, getScalarIndexOption } from '@/utils';
 import CreateForm from './CreateForm';
 import { IndexType, IndexExtraParam } from './Types';
 
 const CreateIndex = (props: {
   collectionName: string;
   fieldType: DataTypeStringEnum;
+  elementType?: DataTypeStringEnum;
   dataType: DataTypeEnum;
   handleCreate: (params: IndexExtraParam, index_name: string) => void;
   handleCancel: () => void;
@@ -36,6 +37,7 @@ const CreateIndex = (props: {
   const {
     collectionName,
     fieldType,
+    elementType,
     handleCreate,
     handleCancel,
     fieldName,
@@ -163,23 +165,12 @@ const CreateIndex = (props: {
           break;
       }
     } else {
-      switch (fieldType) {
-        case DataTypeStringEnum.VarChar:
-          options = [
-            ...getOptions(
-              indexTrans('scalar'),
-              INDEX_OPTIONS_MAP[DataTypeEnum.VarChar]
-            ),
-          ];
-          break;
-        default:
-          options = [
-            ...getOptions(indexTrans('scalar'), [
-              { label: 'INVERTED', value: INDEX_TYPES_ENUM.INVERTED },
-              { label: 'STL sort', value: INDEX_TYPES_ENUM.SORT },
-            ]),
-          ];
-      }
+      options = [
+        ...getOptions(
+          indexTrans('scalar'),
+          getScalarIndexOption(fieldType, elementType)
+        ),
+      ];
     }
 
     return [...autoOption, ...options];
@@ -253,7 +244,7 @@ const CreateIndex = (props: {
     // reset index params
     let paramsForm: { [key in string]: string } = {};
     // m is selector not input
-    (INDEX_CONFIG[type].create || [])
+    ((INDEX_CONFIG[type] && INDEX_CONFIG[type].create) || [])
       .filter(t => t !== 'm')
       .forEach(item => {
         paramsForm[item] = '';
@@ -280,7 +271,7 @@ const CreateIndex = (props: {
     <DialogTemplate
       title={dialogTrans('createTitle', {
         type: indexTrans('index'),
-        name: collectionName,
+        name: fieldName,
       })}
       handleClose={handleCancel}
       confirmLabel={btnTrans('create')}

+ 1 - 0
client/src/pages/databases/collections/schema/IndexTypeElement.tsx

@@ -111,6 +111,7 @@ const IndexTypeElement: FC<{
             fieldName={field.name}
             dataType={field.dataType as unknown as DataTypeEnum}
             fieldType={field.data_type as DataTypeStringEnum}
+            elementType={field.element_type as DataTypeStringEnum}
             dimension={Number(field.dimension)}
             handleCancel={handleCloseDialog}
             handleCreate={requestCreateIndex}

+ 59 - 1
client/src/utils/Form.ts

@@ -1,5 +1,11 @@
 import { Option } from '@/components/customSelector/Types';
-import { METRIC_TYPES_VALUES, DataTypeEnum } from '@/consts';
+import {
+  METRIC_TYPES_VALUES,
+  DataTypeEnum,
+  SCALAR_INDEX_OPTIONS,
+  DataTypeStringEnum,
+  INDEX_TYPES_ENUM,
+} from '@/consts';
 import { IForm } from '@/hooks';
 import { IndexType } from '@/pages/databases/collections/schema/Types';
 
@@ -88,3 +94,55 @@ export const getMetricOptions = (
       return [];
   }
 };
+
+export const getScalarIndexOption = (
+  fieldType: DataTypeStringEnum,
+  elementType?: DataTypeStringEnum
+): Option[] => {
+  // Helper function to check if a type is numeric
+  const isNumericType = (type: DataTypeStringEnum): boolean =>
+    ['Int8', 'Int16', 'Int32', 'Int64', 'Float', 'Double'].includes(type);
+
+  // Helper function to check if a type is valid for bitmap
+  const isBitmapSupportedType = (type: DataTypeStringEnum): boolean =>
+    ['Bool', 'Int8', 'Int16', 'Int32', 'Int64', 'VarChar'].includes(type);
+
+  // Initialize the options array
+  const options: Option[] = [];
+
+  // Add options based on fieldType
+  if (fieldType === DataTypeStringEnum.VarChar) {
+    options.push(
+      SCALAR_INDEX_OPTIONS.find(
+        opt => opt.value === INDEX_TYPES_ENUM.MARISA_TRIE
+      )!
+    );
+  }
+
+  if (isNumericType(fieldType)) {
+    options.push(
+      SCALAR_INDEX_OPTIONS.find(opt => opt.value === INDEX_TYPES_ENUM.SORT)!
+    );
+  }
+
+  if (
+    fieldType === DataTypeStringEnum.Array &&
+    elementType &&
+    isBitmapSupportedType(elementType)
+  ) {
+    options.push(
+      SCALAR_INDEX_OPTIONS.find(opt => opt.value === INDEX_TYPES_ENUM.BITMAP)!
+    );
+  } else if (isBitmapSupportedType(fieldType)) {
+    options.push(
+      SCALAR_INDEX_OPTIONS.find(opt => opt.value === INDEX_TYPES_ENUM.BITMAP)!
+    );
+  }
+
+  // INVERTED index is a general-purpose index for all scalar fields
+  options.push(
+    SCALAR_INDEX_OPTIONS.find(opt => opt.value === INDEX_TYPES_ENUM.INVERTED)!
+  );
+
+  return options;
+};