Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions client/src/components/customDialog/DialogTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { FC, useRef } from 'react';
import { FC, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { DialogContent, DialogActions, Theme } from '@mui/material';
import {
DialogContent,
DialogActions,
Theme,
CircularProgress,
} from '@mui/material';
import { DialogContainerProps } from './Types';
import CustomDialogTitle from './CustomDialogTitle';
import CustomButton from '../customButton/CustomButton';
Expand Down Expand Up @@ -39,7 +44,7 @@ const useStyles = makeStyles((theme: Theme) => ({
paddingBottom: theme.spacing(2),
justifyContent: 'space-between',
'& .btn': {
margin: theme.spacing(.5),
margin: theme.spacing(0.5),
},
},
}));
Expand All @@ -62,6 +67,7 @@ const DialogTemplate: FC<DialogContainerProps> = ({
codeBlocksData = [],
dialogClass = '',
}) => {
const [confirming, setConfirming] = useState(false);
const { t } = useTranslation('btn');
const cancel = cancelLabel || t('cancel');
const confirm = confirmLabel || t('confirm');
Expand All @@ -70,9 +76,15 @@ const DialogTemplate: FC<DialogContainerProps> = ({

const dialogRef = useRef(null);

const _handleConfirm = (event: React.FormEvent<HTMLFormElement>) => {
handleConfirm();
const _handleConfirm = async (event: React.FormEvent<HTMLFormElement>) => {
setConfirming(true);
event.preventDefault();
try {
await handleConfirm();
} catch (error) {
} finally {
setConfirming(false);
}
};

return (
Expand All @@ -98,6 +110,7 @@ const DialogTemplate: FC<DialogContainerProps> = ({
onClick={onCancel}
name="cancel"
className="btn"
disabled={confirming}
>
{cancel}
</CustomButton>
Expand All @@ -106,11 +119,11 @@ const DialogTemplate: FC<DialogContainerProps> = ({
type="submit"
variant="contained"
color="primary"
disabled={confirmDisabled}
disabled={confirming || confirmDisabled}
name="confirm"
className="btn"
>
{confirm}
{confirming ? <CircularProgress size={16} /> : confirm}
</CustomButton>
</div>
</DialogActions>
Expand Down
4 changes: 4 additions & 0 deletions client/src/i18n/cn/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const collectionTrans = {
partitionKey: '分区键',
partitionKeyTooltip:
'Milvus将根据分区键字段中的值在分区中存储entities。只支持一个Int64或VarChar字段。',
paritionKeyDisabledTooltip: '只允许一个分区字段,同时分区键字段不能用作主键字段。',
enableDynamicSchema: '启用动态Schema',
analyzer: '分词器',
enableMatch: '启用匹配',
Expand All @@ -72,6 +73,9 @@ const collectionTrans = {
nullableTooltip: '字段是否可以为 null,nullable 字段不能用作分区键。',
defaultValue: '默认值',
defaultValueTooltip: '字段的默认值, 不支持JSON 和 Array。',
loadCollectionAfterCreate: '创建后加载collection',
loadCollectionAfterCreateTooltip:
'Attu 将使用 AUTOINDEX 为所有字段创建索引,然后加载Collection。',

// load dialog
loadTitle: '加载Collection',
Expand Down
5 changes: 5 additions & 0 deletions client/src/i18n/en/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const collectionTrans = {
partitionKey: 'Partition Key',
partitionKeyTooltip:
' Milvus will store entities in a partition according to the values in the partition key field. Only one Int64 or VarChar field is supported.',
paritionKeyDisabledTooltip:
'Only one field can be marked as paritition key and field marked as nullable cannot be used as partition key.',
enableDynamicSchema: 'Dynamic Schema',
analyzer: 'Analyzer',
enableMatch: 'Enable Match',
Expand All @@ -78,6 +80,9 @@ const collectionTrans = {
defaultValue: 'Default',
defaultValueTooltip:
'Default value of the field, JSON and Array types are not supported.',
loadCollectionAfterCreate: 'Load collection immediately after creation',
loadCollectionAfterCreateTip:
'Attu will create indexes for fields using AUTOINDEX and then load the collection.',

// load dialog
loadTitle: 'Load Collection',
Expand Down
69 changes: 54 additions & 15 deletions client/src/pages/dialogs/CreateCollectionDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { makeStyles } from '@mui/styles';

const useStyles = makeStyles((theme: Theme) => ({
dialog: {
minWidth: 880,
minWidth: 720,
},
container: {
display: 'flex',
Expand Down Expand Up @@ -62,12 +62,18 @@ const useStyles = makeStyles((theme: Theme) => ({
input: {
width: '100%',
},
dynamicField: {
chexBoxArea: {
paddingTop: 8,
fontSize: 14,
marginLeft: -8,
'& label': {
display: 'inline-block',
},
borderTop: `1px solid ${theme.palette.divider}`,
},
consistencySelect: {
width: '50%',
marginBottom: 16,
},
}));

Expand All @@ -85,6 +91,7 @@ const CreateCollectionDialog: FC<CollectionCreateProps> = ({ onCreate }) => {
description: '',
autoID: true,
enableDynamicField: false,
loadAfterCreate: true,
});

const [consistencyLevel, setConsistencyLevel] =
Expand Down Expand Up @@ -137,13 +144,14 @@ const CreateCollectionDialog: FC<CollectionCreateProps> = ({ onCreate }) => {
});
};

const changeEnableDynamicField = (
const updateCheckBox = (
event: ChangeEvent<any>,
key: string,
value: boolean
) => {
setForm({
...form,
enableDynamicField: value,
[key]: value,
});
};

Expand Down Expand Up @@ -372,17 +380,48 @@ const CreateCollectionDialog: FC<CollectionCreateProps> = ({ onCreate }) => {
variant="filled"
/>
</fieldset>
<fieldset className={classes.dynamicField}>
<CustomToolTip title={collectionTrans('partitionKeyTooltip')}>
<>
<Checkbox
checked={!!form.enableDynamicField}
size="small"
onChange={changeEnableDynamicField}
/>
{collectionTrans('enableDynamicSchema')}
</>
</CustomToolTip>
<fieldset className={classes.chexBoxArea}>
<div>
<CustomToolTip title={collectionTrans('partitionKeyTooltip')}>
<label htmlFor="enableDynamicField">
<Checkbox
id="enableDynamicField"
checked={!!form.enableDynamicField}
size="small"
onChange={event => {
updateCheckBox(
event,
'enableDynamicField',
!form.enableDynamicField
);
}}
/>
{collectionTrans('enableDynamicSchema')}
</label>
</CustomToolTip>
</div>

<div>
<CustomToolTip
title={collectionTrans('loadCollectionAfterCreateTip')}
>
<label htmlFor="loadAfterCreate">
<Checkbox
id="loadAfterCreate"
checked={!!form.loadAfterCreate}
size="small"
onChange={event => {
updateCheckBox(
event,
'loadAfterCreate',
!form.loadAfterCreate
);
}}
/>
{collectionTrans('loadCollectionAfterCreate')}
</label>
</CustomToolTip>
</div>
</fieldset>
</section>
</div>
Expand Down
14 changes: 7 additions & 7 deletions client/src/pages/dialogs/create/CreateFields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ const useStyles = makeStyles((theme: Theme) => ({
},
title: {
fontSize: 14,
marginTop: theme.spacing(1),
marginBottom: theme.spacing(1),
marginTop: theme.spacing(0),
marginBottom: theme.spacing(1.5),
'& button': {
position: 'relative',
top: '-1px',
Expand Down Expand Up @@ -492,23 +492,23 @@ const CreateFields: FC<CreateFieldsProps> = ({
field: FieldType,
fields: FieldType[]
) => {
const disabled =
(fields.some(f => f.is_partition_key) && !field.is_partition_key) ||
field.nullable;
return (
<div className={classes.setting}>
<Checkbox
checked={!!field.is_partition_key}
size="small"
disabled={
(fields.some(f => f.is_partition_key) && !field.is_partition_key) ||
field.nullable
}
disabled={disabled}
onChange={() => {
changeFields(field.id!, {
is_partition_key: !field.is_partition_key,
});
}}
/>
<CustomToolTip
title={collectionTrans('partitionKeyTooltip')}
title={collectionTrans(disabled ? 'paritionKeyDisabledTooltip' :'partitionKeyTooltip')}
placement="top"
>
<>{collectionTrans('partitionKey')}</>
Expand Down
33 changes: 32 additions & 1 deletion server/src/collections/collections.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { NextFunction, Request, Response, Router } from 'express';
import { dtoValidationMiddleware } from '../middleware/validation';
import { CollectionsService } from './collections.service';
import { LoadCollectionReq } from '@zilliz/milvus2-sdk-node';
import {
LoadCollectionReq,
IndexType,
MetricType,
} from '@zilliz/milvus2-sdk-node';
import {
CreateAliasDto,
CreateCollectionDto,
Expand Down Expand Up @@ -168,11 +172,38 @@ export class CollectionController {

async createCollection(req: Request, res: Response, next: NextFunction) {
const createCollectionData = req.body;

if (createCollectionData.loadAfterCreate) {
// build index_params for all fields
const fields = createCollectionData.fields;
const index_params = fields.map((field: any) => {
const params: any = {
field_name: field.name,
index_type: IndexType.AUTOINDEX,
};

if (field.is_function_output) {
params.metric_type = MetricType.BM25;
}

return params;
});
createCollectionData.index_params = index_params;
}

try {
const result = await this.collectionsService.createCollection(
req.clientId,
createCollectionData
);

// load collection after create
if (createCollectionData.loadAfterCreate) {
await this.collectionsService.loadCollectionAsync(req.clientId, {
collection_name: createCollectionData.collection_name,
db_name: req.db_name,
});
}
res.send(result);
} catch (error) {
next(error);
Expand Down
Loading