Skip to content

Commit

Permalink
add index options builder
Browse files Browse the repository at this point in the history
Signed-off-by: Shenoy Pratik <[email protected]>
  • Loading branch information
ps48 committed Sep 28, 2023
1 parent aac14f6 commit 2838ca7
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 98 deletions.
14 changes: 14 additions & 0 deletions common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ export const ACCELERATION_TIME_INTERVAL = [
];

export const ACCELERATION_ADD_FIELDS_TEXT = '(add fields here)';

export const ACCELERATION_INDEX_NAME_INFO = `All OpenSearch acceleration indices have a naming format of pattern: \`prefix_<index name>_suffix\`. They share a common prefix structure, which is \`flint_<data source name>_<database name>_<table name>_\`. Additionally, they may have a suffix that varies based on the index type.
##### Skipping Index
- For 'Skipping' indices, a fixed index name 'skipping' is used, and this name cannot be modified by the user. The suffix added to this type is \`_index\`.
- An example of a 'Skipping' index name would be: \`flint_mydatasource_mydb_mytable_skipping_index\`.
##### Covering Index
- 'Covering' indices allow users to specify their index name. The suffix added to this type is \`_index\`.
- For instance, a 'Covering' index name could be: \`flint_mydatasource_mydb_mytable_myindexname_index\`.
##### Materialized View Index
- 'Materialized View' indices also enable users to define their index name, but they do not have a suffix.
- An example of a 'Materialized View' index name might look like: \`flint_mydatasource_mydb_mytable_myindexname\`.
##### Note:
- All user given index names must be in lowercase letters. Cannot begin with underscores or hyphens. Spaces, commas, and characters :, ", *, +, /, \, |, ?, #, >, or < are not allowed.
`;
18 changes: 14 additions & 4 deletions common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

export type AggregationNameType = 'skipping' | 'covering' | 'materialized';
export type AggregationFunctionType = 'count' | 'sum' | 'avg' | 'max' | 'min';

export interface MaterializedViewColumn {
id: string;
functionName: AggregationNameType;
functionName: AggregationFunctionType;
functionParam: string;
fieldAlias?: string;
}
Expand All @@ -32,16 +32,26 @@ export interface RefreshIntervalType {

export type AccelerationIndexType = 'skipping' | 'covering' | 'materialized';

export interface GroupByTumbleType {
timeField: string;
tumbleWindow: number;
tumbleInterval: string;
}

export interface materializedViewQueryType {
ColumnsValues: MaterializedViewColumn[];
GroupByTumbleValue: GroupByTumbleType;
}

export interface CreateAccelerationForm {
dataSource: string;
database: string;
dataTable: string;
dataTableFields: DataTableFieldsType[];
accelerationIndexType: AccelerationIndexType;
queryBuilderType: 'visual' | 'code';
skippingIndexQueryData: SkippingIndexRowType[];
coveringIndexQueryData: string;
materializedViewQueryData: string;
materializedViewQueryData: materializedViewQueryType;
accelerationIndexName: string;
primaryShardsCount: number;
replicaShardsCount: number;
Expand Down
5 changes: 2 additions & 3 deletions public/components/acceleration/create/create_acceleration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import React, { useState } from 'react';
import { CreateAccelerationHeader } from './create_acceleration_header';
import { CautionBannerCallout } from './caution_banner_callout';
import { AccelerationDataSourceSelector } from '../selectors/source_selector';
import { CreateAccelerationForm } from '../../../../common/types/';
import { CreateAccelerationForm, materializedViewQueryType } from '../../../../common/types/';
import { QueryVisualEditor } from '../visual_editors/query_visual_editor';
import { accelerationQueryBuilder } from '../visual_editors/query_builder';
import { IndexSettingOptions } from '../selectors/index_setting_options';
Expand All @@ -41,10 +41,9 @@ export const CreateAcceleration = ({
database: '',
dataTableFields: [],
accelerationIndexType: 'skipping',
queryBuilderType: 'visual',
skippingIndexQueryData: [],
coveringIndexQueryData: '',
materializedViewQueryData: '',
materializedViewQueryData: {} as materializedViewQueryType,
accelerationIndexName: '',
primaryShardsCount: 5,
replicaShardsCount: 1,
Expand Down
105 changes: 85 additions & 20 deletions public/components/acceleration/selectors/define_index_options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,27 @@
*/

import React, { ChangeEvent, useEffect, useState } from 'react';
import {
EuiButton,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiIconTip,
EuiLink,
EuiMarkdownFormat,
EuiModal,
EuiModalBody,
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiSpacer,
EuiText,
EuiHorizontalRule,
} from '@elastic/eui';
import { CreateAccelerationForm } from '../../../../common/types';
import { EuiFieldText, EuiFormRow, EuiSpacer, EuiText, EuiToolTip } from '@elastic/eui';
import { validateIndexName } from '../create/utils';
import { ACCELERATION_INDEX_NAME_INFO } from '../../../../common/constants';

interface DefineIndexOptionsProps {
accelerationFormData: CreateAccelerationForm;
Expand All @@ -18,6 +36,34 @@ export const DefineIndexOptions = ({
setAccelerationFormData,
}: DefineIndexOptionsProps) => {
const [indexName, setIndexName] = useState('');
const [isModalVisible, setIsModalVisible] = useState(false);

let modal;

if (isModalVisible) {
modal = (
<EuiModal maxWidth={850} onClose={() => setIsModalVisible(false)}>
<EuiModalHeader>
<EuiModalHeaderTitle>
<h1>Acceleration index naming</h1>
</EuiModalHeaderTitle>
</EuiModalHeader>
<EuiModalBody>
<EuiHorizontalRule size="full" margin="s" />
<EuiFlexGroup>
<EuiFlexItem>
<EuiMarkdownFormat>{ACCELERATION_INDEX_NAME_INFO}</EuiMarkdownFormat>
</EuiFlexItem>
</EuiFlexGroup>
</EuiModalBody>
<EuiModalFooter>
<EuiButton onClick={() => setIsModalVisible(false)} fill>
Close
</EuiButton>
</EuiModalFooter>
</EuiModal>
);
}

const onChangeIndexName = (e: ChangeEvent<HTMLInputElement>) => {
setAccelerationFormData({ ...accelerationFormData, accelerationIndexName: e.target.value });
Expand All @@ -30,6 +76,28 @@ export const DefineIndexOptions = ({
: setIndexName('');
}, [accelerationFormData.accelerationIndexType]);

const getPreprend = () => {
const dataSource =
accelerationFormData.dataSource !== ''
? accelerationFormData.dataSource
: '{Datasource Name}';
const database =
accelerationFormData.database !== '' ? accelerationFormData.database : '{Database Name}';
const dataTable =
accelerationFormData.dataTable !== '' ? accelerationFormData.dataTable : '{Table Name}';
const prependValue = `flint_${dataSource}_${database}_${dataTable}_`;
return [
prependValue,
<EuiIconTip type="iInCircle" color="subdued" content={prependValue} position="top" />,
];
};

const getAppend = () => {
const appendValue =
accelerationFormData.accelerationIndexType === 'materialized' ? '' : '_index';
return appendValue;
};

return (
<>
<EuiText data-test-subj="define-index-header">
Expand All @@ -40,27 +108,24 @@ export const DefineIndexOptions = ({
label="Index name"
helpText='Must be in lowercase letters. Cannot begin with underscores or hyphens. Spaces, commas, and characters :, ", *, +, /, \, |, ?, #, >, or < are not allowed.
Prefix and suffix are added to the name of generated OpenSearch index.'
labelAppend={
<EuiText size="xs">
<EuiLink onClick={() => setIsModalVisible(true)}>Help</EuiLink>
</EuiText>
}
>
<EuiToolTip
position="right"
content={
accelerationFormData.accelerationIndexType === 'skipping'
? 'Skipping Index name follows a pre-defined in the format `flint_datasource_datatable_skipping_index` and cannot be changed.'
: 'Generated OpenSearch index names follow the format `flint_datasource_datatable_<covering_index_name>_index` and `flint_datasource_datatable_<materialized_view>`'
}
>
<EuiFieldText
placeholder="Enter Index Name"
value={indexName}
onChange={onChangeIndexName}
aria-label="Enter Index Name"
prepend={`flint_${accelerationFormData.dataSource}_${accelerationFormData.database}_`}
append={accelerationFormData.accelerationIndexType === 'materialized' ? '' : '_index'}
disabled={accelerationFormData.accelerationIndexType === 'skipping'}
isInvalid={validateIndexName(indexName)}
/>
</EuiToolTip>
<EuiFieldText
placeholder="Enter index name"
value={indexName}
onChange={onChangeIndexName}
aria-label="Enter Index Name"
prepend={getPreprend()}
append={getAppend()}
disabled={accelerationFormData.accelerationIndexType === 'skipping'}
isInvalid={validateIndexName(indexName)}
/>
</EuiFormRow>
{modal}
</>
);
};
37 changes: 19 additions & 18 deletions public/components/acceleration/selectors/index_setting_options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,25 +166,26 @@ export const IndexSettingOptions = ({
/>
</EuiFormRow>
)}

<EuiFormRow
label={
accelerationFormData.accelerationIndexType === 'materialized'
? 'Checkpoint location'
: 'Checkpoint location - optional'
}
helpText="The HDFS compatible file system location path for incremental refresh job checkpoint. Applicable when auto refresh is enabled."
>
<EuiFieldText
placeholder="s3://checkpoint/location"
value={checkpoint}
onChange={onChangeCheckpoint}
aria-label="Use aria labels when no actual label is in use"
isInvalid={
accelerationFormData.accelerationIndexType === 'materialized' && checkpoint === ''
{refreshTypeSelected === autoRefreshId && (
<EuiFormRow
label={
accelerationFormData.accelerationIndexType === 'materialized'
? 'Checkpoint location'
: 'Checkpoint location - optional'
}
/>
</EuiFormRow>
helpText="The HDFS compatible file system location path for incremental refresh job checkpoint. Applicable when auto refresh is enabled."
>
<EuiFieldText
placeholder="s3://checkpoint/location"
value={checkpoint}
onChange={onChangeCheckpoint}
aria-label="Use aria labels when no actual label is in use"
isInvalid={
accelerationFormData.accelerationIndexType === 'materialized' && checkpoint === ''
}
/>
</EuiFormRow>
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
EuiText,
EuiFlexItem,
EuiFlexGroup,
EuiComboBoxOptionOption,
} from '@elastic/eui';
import React, { useEffect, useState } from 'react';
import { CreateAccelerationForm } from '../../../../../common/types';
Expand All @@ -31,7 +32,7 @@ export const CoveringIndexBuilder = ({
const [columnsValue, setColumnsValue] = useState('');
const [selectedOptions, setSelected] = useState([]);

const onChange = (selectedOptions) => {
const onChange = (selectedOptions: EuiComboBoxOptionOption[]) => {
setSelected(selectedOptions);
};

Expand All @@ -51,6 +52,7 @@ export const CoveringIndexBuilder = ({
) +
')';
}
setAccelerationFormData({ ...accelerationFormData, coveringIndexQueryData: expresseionValue });
setColumnsValue(expresseionValue);
}, [selectedOptions]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from '@elastic/eui';

import {
AggregationNameType,
AggregationFunctionType,
CreateAccelerationForm,
MaterializedViewColumn,
} from '../../../../../common/types';
Expand Down Expand Up @@ -55,6 +55,7 @@ export const AddColumnPopOver = ({
setSelectedField([{ label: defaultFieldName }]);
}
};

const resetValues = () => {
setSelectedFunction([ACCELERATION_AGGREGRATION_FUNCTIONS[0]]);
resetSelectedField();
Expand All @@ -73,14 +74,6 @@ export const AddColumnPopOver = ({
resetSelectedField();
}, []);

const loadAggregationFields = () => {
let aggFields = _.map(accelerationFormData.dataTableFields, (x) => {
return { label: x.fieldName };
});
if (selectedField.length > 0 && selectedField[0].label === 'count')
aggFields = [{ label: '*' }, ...aggFields];
return aggFields;
};
return (
<EuiPopover
panelPaddingSize="s"
Expand Down Expand Up @@ -117,7 +110,12 @@ export const AddColumnPopOver = ({
<EuiFormRow label="Aggregation field">
<EuiComboBox
singleSelection={{ asPlainText: true }}
options={loadAggregationFields()}
options={[
{ label: '*', disabled: selectedFunction[0].label !== 'count' },
..._.map(accelerationFormData.dataTableFields, (x) => {
return { label: x.fieldName };
}),
]}
selectedOptions={selectedField}
onChange={setSelectedField}
/>
Expand All @@ -139,7 +137,7 @@ export const AddColumnPopOver = ({
...columnExpressionValues,
{
id: newId,
functionName: selectedFunction[0].label as AggregationNameType,
functionName: selectedFunction[0].label as AggregationFunctionType,
functionParam: selectedField[0].label,
fieldAlias: selectedAlias,
},
Expand Down
Loading

0 comments on commit 2838ca7

Please sign in to comment.