Browse Source

support index name and create index on scalar fields

Signed-off-by: nameczz <zizhao.chen@zilliz.com>
nameczz 3 years ago
parent
commit
17bf86c9c3

+ 8 - 2
client/src/components/advancedSearch/Condition.tsx

@@ -69,6 +69,9 @@ const Condition: FC<ConditionProps> = props => {
         const legalValues = ['false', 'true'];
         isLegal = legalValues.includes(conditionValueWithNoSpace);
         break;
+      case DataTypeStringEnum.VarChar:
+        isLegal = conditionValueWithNoSpace !== '';
+        break;
       default:
         isLegal = false;
         break;
@@ -112,7 +115,11 @@ const Condition: FC<ConditionProps> = props => {
   // Value input change.
   const handleValueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
     const value = event.target.value;
-    setConditionValue(value);
+    const type = conditionField?.type;
+    console.log('---value cahnge ---', type, value);
+    setConditionValue(
+      type === DataTypeStringEnum.VarChar ? `"${value}"` : value
+    );
   };
 
   return (
@@ -139,7 +146,6 @@ const Condition: FC<ConditionProps> = props => {
         variant="filled"
         // size="small"
         onChange={handleValueChange}
-        value={conditionValue}
         error={!isValuelegal}
       />
       <IconButton

+ 4 - 0
client/src/components/layout/GlobalEffect.tsx

@@ -41,6 +41,10 @@ const GlobalEffect = (props: { children: React.ReactNode }) => {
         }
         if (response.data) {
           const { message: errMsg } = response.data;
+          console.log('-----err ----', errMsg);
+          if (errMsg.includes('no index is created')) {
+            return Promise.reject(error);
+          }
           // We need check status 401 in login page
           // So server will return 500 when change the user password.
           errMsg && openSnackBar(errMsg, 'error');

+ 6 - 0
client/src/consts/Milvus.tsx

@@ -139,6 +139,12 @@ export const INDEX_OPTIONS_MAP = {
     label: v,
     value: v,
   })),
+  [DataTypeEnum.VarChar]: [
+    {
+      label: 'marisa-trie',
+      value: 'marisa-trie',
+    },
+  ],
 };
 
 export const METRIC_OPTIONS_MAP = {

+ 14 - 5
client/src/http/Index.ts

@@ -12,6 +12,7 @@ import BaseModel from './BaseModel';
 export class IndexHttp extends BaseModel implements IndexView {
   params!: { key: string; value: string }[];
   field_name!: string;
+  index_name!: string;
 
   constructor(props: {}) {
     super(props);
@@ -22,12 +23,17 @@ export class IndexHttp extends BaseModel implements IndexView {
 
   static async getIndexStatus(
     collectionName: string,
-    fieldName: string
+    fieldName: string,
+    indexName: string
   ): Promise<{ state: IndexState }> {
     const path = `${this.BASE_URL}/state`;
     return super.search({
       path,
-      params: { collection_name: collectionName, field_name: fieldName },
+      params: {
+        collection_name: collectionName,
+        field_name: fieldName,
+        index_name: indexName,
+      },
     });
   }
 
@@ -60,7 +66,8 @@ export class IndexHttp extends BaseModel implements IndexView {
 
   static async getIndexBuildProgress(
     collectionName: string,
-    fieldName: string
+    fieldName: string,
+    indexName: string
   ) {
     const path = `${this.BASE_URL}/progress`;
     return super.search({
@@ -68,8 +75,7 @@ export class IndexHttp extends BaseModel implements IndexView {
       params: {
         collection_name: collectionName,
         field_name: fieldName,
-        // user can't set index_name, use empty string as its value
-        index_name: '',
+        index_name: indexName,
       },
     });
   }
@@ -77,6 +83,9 @@ export class IndexHttp extends BaseModel implements IndexView {
   get _indexType() {
     return this.params.find(p => p.key === 'index_type')?.value || '';
   }
+  get _indexName() {
+    return this.index_name;
+  }
 
   get _indexParameterPairs() {
     const metricType = this.params.filter(v => v.key === 'metric_type');

+ 84 - 29
client/src/pages/schema/Create.tsx

@@ -8,16 +8,14 @@ import {
   DEFAULT_VECTORS,
   INDEX_CONFIG,
   INDEX_OPTIONS_MAP,
-  MetricType,
   METRIC_TYPES_VALUES,
 } from '../../consts/Milvus';
 import { useFormValidation } from '../../hooks/Form';
 import { getCreateIndexJSCode } from '../../utils/code/Js';
 import { getCreateIndexPYCode } from '../../utils/code/Py';
 import { formatForm, getMetricOptions } from '../../utils/Form';
-import { getEmbeddingType } from '../../utils/search';
 import { computMilvusRecommonds, formatSize } from '../../utils/SizingTool';
-import { DataTypeStringEnum } from '../collections/Types';
+import { DataTypeEnum, DataTypeStringEnum } from '../collections/Types';
 import CreateForm from './CreateForm';
 import SizingInfo from './SizingInfo';
 import { IndexType, IndexExtraParam, INDEX_TYPES_ENUM } from './Types';
@@ -25,7 +23,7 @@ import { IndexType, IndexExtraParam, INDEX_TYPES_ENUM } from './Types';
 const CreateIndex = (props: {
   collectionName: string;
   fieldType: DataTypeStringEnum;
-  handleCreate: (params: IndexExtraParam) => void;
+  handleCreate: (params: IndexExtraParam, index_name: string) => void;
   handleCancel: () => void;
 
   // used for code mode
@@ -47,20 +45,35 @@ const CreateIndex = (props: {
   const { t: btnTrans } = useTranslation('btn');
   const { t: commonTrans } = useTranslation();
 
-  const defaultIndexType =
-    fieldType === 'BinaryVector'
-      ? INDEX_TYPES_ENUM.BIN_IVF_FLAT
-      : INDEX_TYPES_ENUM.IVF_FLAT;
-  const defaultMetricType =
-    fieldType === 'BinaryVector'
-      ? METRIC_TYPES_VALUES.HAMMING
-      : METRIC_TYPES_VALUES.L2;
+  const defaultIndexType = useMemo(() => {
+    switch (fieldType) {
+      case DataTypeStringEnum.BinaryVector:
+        return INDEX_TYPES_ENUM.BIN_IVF_FLAT;
+      case DataTypeStringEnum.FloatVector:
+        return INDEX_TYPES_ENUM.IVF_FLAT;
+      case DataTypeStringEnum.VarChar:
+        return INDEX_TYPES_ENUM.MARISA_TRIE;
+      default:
+        return INDEX_TYPES_ENUM.SORT;
+    }
+  }, [fieldType]);
+
+  const defaultMetricType = useMemo(() => {
+    switch (fieldType) {
+      case DataTypeStringEnum.BinaryVector:
+        return METRIC_TYPES_VALUES.HAMMING;
+      case DataTypeStringEnum.FloatVector:
+        return METRIC_TYPES_VALUES.L2;
+      default:
+        return '';
+    }
+  }, [fieldType]);
 
   const [indexSetting, setIndexSetting] = useState<{
     index_type: IndexType;
-    metric_type: MetricType;
     [x: string]: string;
   }>({
+    index_name: '',
     index_type: defaultIndexType,
     metric_type: defaultMetricType,
     M: '',
@@ -85,10 +98,15 @@ const CreateIndex = (props: {
     return INDEX_CONFIG[indexSetting.index_type].create;
   }, [indexSetting.index_type]);
 
-  const metricOptions = useMemo(
-    () => getMetricOptions(indexSetting.index_type, fieldType),
-    [indexSetting.index_type, fieldType]
-  );
+  const metricOptions = useMemo(() => {
+    const vectorType = [
+      DataTypeStringEnum.BinaryVector,
+      DataTypeStringEnum.FloatVector,
+    ];
+    return vectorType.includes(fieldType)
+      ? getMetricOptions(indexSetting.index_type, fieldType)
+      : [];
+  }, [indexSetting.index_type, fieldType]);
 
   const extraParams = useMemo(() => {
     const params: { [x: string]: string } = {};
@@ -108,18 +126,33 @@ const CreateIndex = (props: {
   }, [indexCreateParams, indexSetting]);
 
   const indexOptions = useMemo(() => {
-    const type = getEmbeddingType(fieldType);
-    return INDEX_OPTIONS_MAP[type];
+    switch (fieldType) {
+      case DataTypeStringEnum.BinaryVector:
+        return INDEX_OPTIONS_MAP[DataTypeEnum.BinaryVector];
+      case DataTypeStringEnum.FloatVector:
+        return INDEX_OPTIONS_MAP[DataTypeEnum.FloatVector];
+      case DataTypeStringEnum.VarChar:
+        return INDEX_OPTIONS_MAP[DataTypeEnum.VarChar];
+
+      default:
+        return [{ label: 'Ascending', value: 'sort' }];
+    }
   }, [fieldType]);
 
   const checkedForm = useMemo(() => {
+    if (
+      fieldType !== DataTypeStringEnum.BinaryVector &&
+      fieldType !== DataTypeStringEnum.FloatVector
+    ) {
+      return [];
+    }
     const paramsForm: any = { metric_type: indexSetting.metric_type };
     indexCreateParams.forEach(v => {
       paramsForm[v] = indexSetting[v];
     });
     const form = formatForm(paramsForm);
     return form;
-  }, [indexSetting, indexCreateParams]);
+  }, [indexSetting, indexCreateParams, fieldType]);
 
   // sizing info needed param
   const sizingInfo = useMemo(() => {
@@ -176,25 +209,47 @@ const CreateIndex = (props: {
   /**
    * create index code mode
    */
-  const codeBlockData: CodeViewData[] = useMemo(
-    () => [
+  const codeBlockData: CodeViewData[] = useMemo(() => {
+    const vectorTypes = [
+      DataTypeStringEnum.BinaryVector,
+      DataTypeStringEnum.FloatVector,
+    ];
+    const isScalarField = !vectorTypes.includes(fieldType);
+    return [
       {
         label: commonTrans('py'),
         language: CodeLanguageEnum.python,
-        code: getCreateIndexPYCode({ collectionName, fieldName, extraParams }),
+        code: getCreateIndexPYCode({
+          collectionName,
+          fieldName,
+          indexName: indexSetting.index_name,
+          extraParams,
+          isScalarField,
+        }),
       },
       {
         label: commonTrans('js'),
         language: CodeLanguageEnum.javascript,
-        code: getCreateIndexJSCode({ collectionName, fieldName, extraParams }),
+        code: getCreateIndexJSCode({
+          collectionName,
+          fieldName,
+          extraParams,
+          indexName: indexSetting.index_name,
+          isScalarField,
+        }),
       },
-    ],
-    [commonTrans, extraParams, collectionName, fieldName]
-  );
+    ];
+  }, [
+    commonTrans,
+    extraParams,
+    collectionName,
+    fieldName,
+    indexSetting.index_name,
+    fieldType,
+  ]);
 
   const { validation, checkIsValid, disabled, setDisabled, resetValidation } =
     useFormValidation(checkedForm);
-
   // reset index params
   useEffect(() => {
     // no need
@@ -234,7 +289,7 @@ const CreateIndex = (props: {
   };
 
   const handleCreateIndex = () => {
-    handleCreate(extraParams);
+    handleCreate(extraParams, indexSetting.index_name);
   };
 
   const handleShowCode = (event: React.ChangeEvent<{ checked: boolean }>) => {

+ 52 - 23
client/src/pages/schema/CreateForm.tsx

@@ -150,8 +150,31 @@ const CreateForm = (
 
     return result;
   }, [updateForm, warningTrans, indexParams, formValue]);
+
+  const indexNameConfig: ITextfieldConfig = {
+    label: 'Index Name',
+    key: 'index_name',
+    onChange: (value: string) => updateForm('index_name', value),
+    variant: 'filled',
+    placeholder: 'alias name',
+    fullWidth: true,
+    validations: [
+      {
+        rule: 'require',
+        errorText: warningTrans('required', {
+          name: 'Index Name',
+        }),
+      },
+    ],
+    defaultValue: '',
+  };
   return (
     <div className={classes.wrapper}>
+      <CustomInput
+        type="text"
+        textConfig={indexNameConfig}
+        checkValid={checkIsValid}
+      />
       <CustomSelector
         label={indexTrans('type')}
         value={formValue.index_type}
@@ -166,21 +189,25 @@ const CreateForm = (
         variant="filled"
         wrapperClass={classes.select}
       />
+      {metricOptions.length ? (
+        <Typography className={classes.paramTitle}>
+          {commonTrans('param')}
+        </Typography>
+      ) : null}
 
-      <Typography className={classes.paramTitle}>
-        {commonTrans('param')}
-      </Typography>
-      <CustomSelector
-        label={indexTrans('metric')}
-        value={formValue.metric_type}
-        options={metricOptions}
-        onChange={(e: { target: { value: unknown } }) => {
-          const type = e.target.value;
-          updateForm('metric_type', type as string);
-        }}
-        variant="filled"
-        wrapperClass={classes.select}
-      />
+      {metricOptions.length ? (
+        <CustomSelector
+          label={indexTrans('metric')}
+          value={formValue.metric_type}
+          options={metricOptions}
+          onChange={(e: { target: { value: unknown } }) => {
+            const type = e.target.value;
+            updateForm('metric_type', type as string);
+          }}
+          variant="filled"
+          wrapperClass={classes.select}
+        />
+      ) : null}
 
       {indexParams.includes('m') && (
         <CustomSelector
@@ -195,15 +222,17 @@ const CreateForm = (
         />
       )}
 
-      {paramsConfig.map(v => (
-        <CustomInput
-          type="text"
-          textConfig={v}
-          checkValid={checkIsValid}
-          validInfo={validation}
-          key={v.label}
-        />
-      ))}
+      {paramsConfig.length
+        ? paramsConfig.map(v => (
+            <CustomInput
+              type="text"
+              textConfig={v}
+              checkValid={checkIsValid}
+              validInfo={validation}
+              key={v.label}
+            />
+          ))
+        : null}
     </div>
   );
 };

+ 31 - 24
client/src/pages/schema/IndexTypeElement.tsx

@@ -108,11 +108,12 @@ const IndexTypeElement: FC<{
     if (data._indexType !== '' && status !== IndexState.Delete) {
       const { state: status } = await IndexHttp.getIndexStatus(
         collectionName,
-        data._fieldName
+        data._fieldName,
+        data._indexName
       );
       setStatus(status);
     }
-  }, [collectionName, data._fieldName, data._indexType, status]);
+  }, [collectionName, data, status]);
 
   const fetchProgress = useCallback(() => {
     if (timer) {
@@ -120,28 +121,33 @@ const IndexTypeElement: FC<{
     }
     if (data._indexType !== '' && isIndexCreating) {
       timer = setTimeout(async () => {
-        const res = await IndexHttp.getIndexBuildProgress(
-          collectionName,
-          data._fieldName
-        );
+        try {
+          const res = await IndexHttp.getIndexBuildProgress(
+            collectionName,
+            data._fieldName,
+            data._indexName
+          );
 
-        const { indexed_rows, total_rows } = res;
-        const percent = Number(indexed_rows) / Number(total_rows);
-        const value = Math.floor(percent * 100);
-        setCreateProgress(value);
+          const { indexed_rows, total_rows } = res;
+          const percent = Number(indexed_rows) / Number(total_rows);
+          const value = Math.floor(percent * 100);
+          setCreateProgress(value);
 
-        if (value !== 100) {
-          fetchProgress();
-        } else {
-          timer && clearTimeout(timer);
-          // reset build progress
-          setCreateProgress(0);
-          // change index create status
+          if (value !== 100) {
+            fetchProgress();
+          } else {
+            timer && clearTimeout(timer);
+            // reset build progress
+            setCreateProgress(0);
+            // change index create status
+            setStatus(IndexState.Finished);
+          }
+        } catch (error) {
           setStatus(IndexState.Finished);
         }
       }, 500);
     }
-  }, [collectionName, data._fieldName, isIndexCreating, data._indexType]);
+  }, [collectionName, data, isIndexCreating]);
 
   useEffect(() => {
     /**
@@ -151,10 +157,14 @@ const IndexTypeElement: FC<{
     fetchProgress();
   }, [fetchStatus, fetchProgress]);
 
-  const requestCreateIndex = async (params: IndexExtraParam) => {
+  const requestCreateIndex = async (
+    params: IndexExtraParam,
+    index_name: string
+  ) => {
     const indexCreateParam: IndexCreateParam = {
       collection_name: collectionName,
       field_name: data._fieldName,
+      index_name,
       extra_params: params,
     };
     await IndexHttp.createIndex(indexCreateParam);
@@ -188,6 +198,7 @@ const IndexTypeElement: FC<{
     const indexDeleteParam: IndexManageParam = {
       collection_name: collectionName,
       field_name: data._fieldName,
+      index_name: data._indexName,
     };
 
     await IndexHttp.deleteIndex(indexDeleteParam);
@@ -217,13 +228,9 @@ const IndexTypeElement: FC<{
 
   const generateElement = () => {
     // only vector type field is able to create index
-    if (
-      data._fieldType !== 'BinaryVector' &&
-      data._fieldType !== 'FloatVector'
-    ) {
+    if (data._isPrimaryKey) {
       return <div className={classes.item}>--</div>;
     }
-
     // _indexType example: FLAT
     switch (data._indexType) {
       case '': {

+ 11 - 12
client/src/pages/schema/Schema.tsx

@@ -9,7 +9,6 @@ import CustomToolTip from '../../components/customToolTip/CustomToolTip';
 import { FieldHttp } from '../../http/Field';
 import { FieldView } from './Types';
 import IndexTypeElement from './IndexTypeElement';
-import { DataTypeStringEnum } from '../collections/Types';
 import { IndexHttp } from '../../http/Index';
 
 const useStyles = makeStyles((theme: Theme) => ({
@@ -77,10 +76,6 @@ const Schema: FC<{
   const fetchSchemaListWithIndex = async (
     collectionName: string
   ): Promise<FieldView[]> => {
-    const vectorTypes: DataTypeStringEnum[] = [
-      DataTypeStringEnum.BinaryVector,
-      DataTypeStringEnum.FloatVector,
-    ];
     const indexList = await IndexHttp.getIndexInfo(collectionName);
     const schemaList = await FieldHttp.getFields(collectionName);
     let fields: FieldView[] = [];
@@ -88,14 +83,12 @@ const Schema: FC<{
       let field: FieldView = Object.assign(schema, {
         _indexParameterPairs: [],
         _indexType: '',
+        _indexName: '',
       });
-      if (vectorTypes.includes(schema.data_type)) {
-        const index = indexList.find(i => i._fieldName === schema.name);
-
-        field._indexParameterPairs = index?._indexParameterPairs || [];
-        field._indexType = index?._indexType || '';
-        field._createIndexDisabled = indexList.length > 0;
-      }
+      const index = indexList.find(i => i._fieldName === schema.name);
+      field._indexParameterPairs = index?._indexParameterPairs || [];
+      field._indexType = index?._indexType || '';
+      field._indexName = index?._indexName || '';
 
       fields = [...fields, field];
     }
@@ -191,6 +184,12 @@ const Schema: FC<{
       disablePadding: true,
       label: collectionTrans('maxLength'),
     },
+    {
+      id: '_indexName',
+      align: 'left',
+      disablePadding: true,
+      label: 'Index name',
+    },
     {
       id: '_indexTypeElement',
       align: 'left',

+ 8 - 1
client/src/pages/schema/Types.ts

@@ -13,6 +13,8 @@ export enum INDEX_TYPES_ENUM {
   RNSG = 'RNSG',
   BIN_IVF_FLAT = 'BIN_IVF_FLAT',
   BIN_FLAT = 'BIN_FLAT',
+  SORT = 'sort',
+  MARISA_TRIE = 'marisa-trie',
 }
 
 export interface Field {
@@ -47,6 +49,7 @@ export interface Index {
 export interface IndexView {
   _fieldName: string;
   _indexType: string;
+  _indexName: string;
   _indexTypeElement?: ReactElement;
   _indexParameterPairs: { key: string; value: string }[];
   _indexParamElement?: ReactElement;
@@ -63,14 +66,18 @@ export type IndexType =
   | INDEX_TYPES_ENUM.HNSW
   | INDEX_TYPES_ENUM.ANNOY
   | INDEX_TYPES_ENUM.BIN_IVF_FLAT
-  | INDEX_TYPES_ENUM.BIN_FLAT;
+  | INDEX_TYPES_ENUM.BIN_FLAT
+  | INDEX_TYPES_ENUM.MARISA_TRIE
+  | INDEX_TYPES_ENUM.SORT;
 
 export interface IndexManageParam {
   collection_name: string;
   field_name: string;
+  index_name: string;
 }
 
 export interface IndexCreateParam extends IndexManageParam {
+  index_name: string;
   extra_params: IndexExtraParam;
 }
 

+ 8 - 2
client/src/utils/code/Js.ts

@@ -1,15 +1,21 @@
 import { CreateIndexCodeParam } from './Types';
 
 export const getCreateIndexJSCode = (params: CreateIndexCodeParam) => {
-  const { collectionName, fieldName, extraParams } = params;
+  const { collectionName, fieldName, indexName, isScalarField, extraParams } =
+    params;
 
   const jsCode = `import { MilvusClient } from '@zilliz/milvus2-sdk-node';
 const client = new MilvusClient(milvus_address);
 
 client.indexManager.createIndex({
   collection_name: '${collectionName}',
+  index_name:'${indexName}',
   field_name: '${fieldName}',
-  extra_params: ${JSON.stringify(extraParams, null, 2)},
+  ${
+    isScalarField
+      ? ''
+      : `extra_params: ${JSON.stringify(extraParams, null, 2)},`
+  }
 });`;
 
   return jsCode;

+ 14 - 4
client/src/utils/code/Py.ts

@@ -10,16 +10,26 @@ const replacer = (key: string, value: any) => {
 };
 
 export const getCreateIndexPYCode = (params: CreateIndexCodeParam) => {
-  const { collectionName, fieldName, extraParams } = params;
-  const index = {
+  const { collectionName, fieldName, indexName, extraParams, isScalarField } =
+    params;
+  const index_params = {
     ...extraParams,
     params: parseValue(extraParams.params),
   };
   const pyCode = `from pymilvus_orm import Collection
 
 collection = Collection('${collectionName}')
-index = ${JSON.stringify(index, replacer, 4)}
-collection.create_index(${fieldName}, index)`;
+${
+  isScalarField
+    ? ''
+    : `index_params = ${JSON.stringify(index_params, replacer, 4)}`
+}
+
+collection.create_index(
+  field_name="${fieldName}",
+  ${isScalarField ? '' : `index_params=index_params,`}
+  index_name="${indexName}"
+)`;
 
   return pyCode;
 };

+ 4 - 2
client/src/utils/code/Types.ts

@@ -1,6 +1,8 @@
-import { IndexExtraParam } from "../../pages/schema/Types";
+import { IndexExtraParam } from '../../pages/schema/Types';
 export interface CreateIndexCodeParam {
   collectionName: string;
   fieldName: string;
-  extraParams: IndexExtraParam
+  indexName: string;
+  extraParams: IndexExtraParam;
+  isScalarField: boolean;
 }

+ 12 - 2
server/generate-csv.ts

@@ -3,7 +3,12 @@ import { createObjectCsvWriter as createCsvWriter } from 'csv-writer';
 // use to test vector insert
 const csvWriter = createCsvWriter({
   path: './vectors.csv',
-  header: [{ id: 'vector', title: 'vector' }],
+  header: [
+    { id: 'vector', title: 'vector' },
+    { id: 'name', title: 'name' },
+    { id: 'age', title: 'age' },
+    { id: 'job', title: 'job' },
+  ],
 });
 
 const records = [];
@@ -20,7 +25,12 @@ const generateVector = (dimension: number) => {
 
 while (records.length < 50000) {
   const value = generateVector(4);
-  records.push({ vector: value });
+  records.push({
+    vector: value,
+    name: `${records.length}_id`,
+    age: records.length * 2,
+    job: Math.random() * 1000 > 500 ? 'designer' : 'programer',
+  });
 }
 
 csvWriter

+ 32 - 17
server/src/schema/schema.controller.ts

@@ -1,9 +1,9 @@
-import { NextFunction, Request, Response, Router } from "express";
-import { dtoValidationMiddleware } from "../middlewares/validation";
-import { SchemaService } from "./schema.service";
-import { milvusService } from "../milvus";
+import { NextFunction, Request, Response, Router } from 'express';
+import { dtoValidationMiddleware } from '../middlewares/validation';
+import { SchemaService } from './schema.service';
+import { milvusService } from '../milvus';
 
-import { ManageIndexDto } from "./dto";
+import { ManageIndexDto } from './dto';
 
 export class SchemaController {
   private router: Router;
@@ -16,31 +16,37 @@ export class SchemaController {
 
   generateRoutes() {
     this.router.post(
-      "/index",
+      '/index',
       dtoValidationMiddleware(ManageIndexDto),
       this.manageIndex.bind(this)
     );
 
-    this.router.get("/index", this.describeIndex.bind(this));
+    this.router.get('/index', this.describeIndex.bind(this));
 
-    this.router.get("/index/progress", this.getIndexBuildProgress.bind(this));
+    this.router.get('/index/progress', this.getIndexBuildProgress.bind(this));
 
-    this.router.get("/index/state", this.getIndexState.bind(this));
+    this.router.get('/index/state', this.getIndexState.bind(this));
 
     return this.router;
   }
 
   async manageIndex(req: Request, res: Response, next: NextFunction) {
-    const { type, collection_name, extra_params, field_name } = req.body;
+    const { type, collection_name, index_name, extra_params, field_name } =
+      req.body;
     try {
       const result =
-        type.toLocaleLowerCase() === "create"
+        type.toLocaleLowerCase() === 'create'
           ? await this.schemaService.createIndex({
               collection_name,
               extra_params,
               field_name,
+              index_name,
             })
-          : await this.schemaService.dropIndex({ collection_name, field_name });
+          : await this.schemaService.dropIndex({
+              collection_name,
+              field_name,
+              index_name,
+            });
       res.send(result);
     } catch (error) {
       next(error);
@@ -48,7 +54,7 @@ export class SchemaController {
   }
 
   async describeIndex(req: Request, res: Response, next: NextFunction) {
-    const data = "" + req.query?.collection_name;
+    const data = '' + req.query?.collection_name;
     try {
       const result = await this.schemaService.describeIndex({
         collection_name: data,
@@ -60,10 +66,14 @@ export class SchemaController {
   }
 
   async getIndexBuildProgress(req: Request, res: Response, next: NextFunction) {
-    const data = "" + req.query?.collection_name;
+    const collection_name = '' + req.query?.collection_name;
+    const index_name = '' + req.query?.index_name;
+    const field_name = '' + req.query?.field_name;
     try {
       const result = await this.schemaService.getIndexBuildProgress({
-        collection_name: data,
+        collection_name,
+        index_name,
+        field_name,
       });
       res.send(result);
     } catch (error) {
@@ -72,10 +82,15 @@ export class SchemaController {
   }
 
   async getIndexState(req: Request, res: Response, next: NextFunction) {
-    const data = "" + req.query?.collection_name;
+    const collection_name = '' + req.query?.collection_name;
+    const index_name = '' + req.query?.index_name;
+    const field_name = '' + req.query?.field_name;
+
     try {
       const result = await this.schemaService.getIndexState({
-        collection_name: data,
+        collection_name,
+        index_name,
+        field_name,
       });
       res.send(result);
     } catch (error) {