Skip to content

Commit

Permalink
[Mappings editor] Add support for constant_keyword field type (#76564) (
Browse files Browse the repository at this point in the history
  • Loading branch information
alisonelizabeth authored Sep 17, 2020
1 parent 873bc2a commit a3ff68e
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { FunctionComponent } from 'react';
import { i18n } from '@kbn/i18n';

import { documentationService } from '../../../../../../services/documentation';
import { UseField, Field, JsonEditorField } from '../../../../shared_imports';
import { getFieldConfig } from '../../../../lib';
import { NormalizedField } from '../../../../types';
import { AdvancedParametersSection, EditFieldFormRow, BasicParametersSection } from '../edit_field';

interface Props {
field: NormalizedField;
}

export const ConstantKeywordType: FunctionComponent<Props> = ({ field }) => {
return (
<>
<BasicParametersSection>
{/* Value field */}
<EditFieldFormRow
title={i18n.translate('xpack.idxMgmt.mappingsEditor.constantKeyword.valueFieldTitle', {
defaultMessage: 'Set value',
})}
description={i18n.translate(
'xpack.idxMgmt.mappingsEditor.constantKeyword.valueFieldDescription',
{
defaultMessage:
'The value of this field for all documents in the index. If not specified, defaults to the value specified in the first document indexed.',
}
)}
defaultToggleValue={field.source?.value !== undefined}
>
<UseField path="value" config={getFieldConfig('value')} component={Field} />
</EditFieldFormRow>
</BasicParametersSection>

<AdvancedParametersSection>
{/* Meta field */}
<EditFieldFormRow
title={i18n.translate('xpack.idxMgmt.mappingsEditor.constantKeyword.metaFieldTitle', {
defaultMessage: 'Set metadata',
})}
description={i18n.translate(
'xpack.idxMgmt.mappingsEditor.constantKeyword.metaFieldDescription',
{
defaultMessage:
'Arbitrary information about the field. Specify as JSON key-value pairs.',
}
)}
defaultToggleValue={field.source?.meta !== undefined}
docLink={{
text: i18n.translate('xpack.idxMgmt.mappingsEditor.constantKeyword.metaDocLinkText', {
defaultMessage: 'Metadata documentation',
}),
href: documentationService.getMetaLink(),
}}
>
<UseField
path="meta"
config={getFieldConfig('meta')}
component={JsonEditorField}
componentProps={{
euiCodeEditorProps: {
height: '300px',
'aria-label': i18n.translate(
'xpack.idxMgmt.mappingsEditor.constantKeyword.metaFieldAriaLabel',
{
defaultMessage: 'metadata field data editor',
}
),
},
}}
/>
</EditFieldFormRow>
</AdvancedParametersSection>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { ObjectType } from './object_type';
import { OtherType } from './other_type';
import { NestedType } from './nested_type';
import { JoinType } from './join_type';
import { ConstantKeywordType } from './constant_keyword_type';
import { RankFeatureType } from './rank_feature_type';
import { WildcardType } from './wildcard_type';

Expand All @@ -54,6 +55,7 @@ const typeToParametersFormMap: { [key in DataType]?: ComponentType<any> } = {
other: OtherType,
nested: NestedType,
join: JoinType,
constant_keyword: ConstantKeywordType,
rank_feature: RankFeatureType,
wildcard: WildcardType,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ export const TYPE_DEFINITION: { [key in DataType]: DataTypeDefinition } = {
</p>
),
},
constant_keyword: {
value: 'constant_keyword',
label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.constantKeywordDescription', {
defaultMessage: 'Constant keyword',
}),
documentation: {
main: '/keyword.html#constant-keyword-field-type',
},
description: () => (
<p>
<FormattedMessage
id="xpack.idxMgmt.mappingsEditor.dataType.constantKeywordLongDescription"
defaultMessage="Constant keyword fields are a special type of keyword fields for fields that contain the same keyword across all documents in the index. Supports the same queries and aggregations as {keyword} fields."
values={{
keyword: <EuiCode inline>{'keyword'}</EuiCode>,
}}
/>
</p>
),
},
numeric: {
value: 'numeric',
label: i18n.translate('xpack.idxMgmt.mappingsEditor.dataType.numericDescription', {
Expand Down Expand Up @@ -822,6 +842,7 @@ export const MAIN_TYPES: MainType[] = [
'binary',
'boolean',
'completion',
'constant_keyword',
'date',
'date_nanos',
'dense_vector',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { INDEX_DEFAULT } from './default_values';
import { TYPE_DEFINITION } from './data_types_definition';

const { toInt } = fieldFormatters;
const { emptyField, containsCharsField, numberGreaterThanField } = fieldValidators;
const { emptyField, containsCharsField, numberGreaterThanField, isJsonField } = fieldValidators;

const commonErrorMessages = {
smallerThanZero: i18n.translate(
Expand Down Expand Up @@ -404,6 +404,88 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio
},
schema: t.string,
},
value: {
fieldConfig: {
defaultValue: '',
type: FIELD_TYPES.TEXT,
label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.valueLabel', {
defaultMessage: 'Value',
}),
},
schema: t.string,
},
meta: {
fieldConfig: {
defaultValue: '',
label: i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.metaLabel', {
defaultMessage: 'Metadata',
}),
helpText: (
<FormattedMessage
id="xpack.idxMgmt.mappingsEditor.parameters.metaHelpText"
defaultMessage="Use JSON format: {code}"
values={{
code: <EuiCode>{JSON.stringify({ arbitrary_key: 'anything_goes' })}</EuiCode>,
}}
/>
),
validations: [
{
validator: isJsonField(
i18n.translate('xpack.idxMgmt.mappingsEditor.parameters.metaFieldEditorJsonError', {
defaultMessage: 'Invalid JSON.',
}),
{ allowEmptyString: true }
),
},
{
validator: ({ value }: ValidationFuncArg<any, string>) => {
if (typeof value !== 'string' || value.trim() === '') {
return;
}

const json = JSON.parse(value);
const valuesAreNotString = Object.values(json).some((v) => typeof v !== 'string');

if (Array.isArray(json)) {
return {
message: i18n.translate(
'xpack.idxMgmt.mappingsEditor.parameters.metaFieldEditorArraysNotAllowedError',
{
defaultMessage: 'Arrays are not allowed.',
}
),
};
} else if (valuesAreNotString) {
return {
message: i18n.translate(
'xpack.idxMgmt.mappingsEditor.parameters.metaFieldEditorOnlyStringValuesAllowedError',
{
defaultMessage: 'Values must be a string.',
}
),
};
}
},
},
],
deserializer: (value: any) => {
if (value === '') {
return value;
}
return JSON.stringify(value, null, 2);
},
serializer: (value: string) => {
const parsed = JSON.parse(value);
// If an empty object was passed, strip out this value entirely.
if (!Object.keys(parsed).length) {
return undefined;
}
return parsed;
},
},
schema: t.any,
},
max_input_length: {
fieldConfig: {
defaultValue: 50,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export type MainType =
| 'geo_point'
| 'geo_shape'
| 'token_count'
| 'constant_keyword'
| 'wildcard'
/**
* 'other' is a special type that only exists inside of MappingsEditor as a placeholder
Expand Down Expand Up @@ -146,7 +147,9 @@ export type ParameterName =
| 'dims'
| 'depth_limit'
| 'relations'
| 'max_shingle_size';
| 'max_shingle_size'
| 'value'
| 'meta';

export interface Parameter {
fieldConfig: FieldConfig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ class DocumentationService {
return `${this.esDocsBase}/ignore-malformed.html`;
}

public getMetaLink() {
return `${this.esDocsBase}/mapping-field-meta.html`;
}

public getFormatLink() {
return `${this.esDocsBase}/mapping-date-format.html`;
}
Expand Down

0 comments on commit a3ff68e

Please sign in to comment.