mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[bug][6.x] Revert mappings lib changes (#22004)
* Remove new library * Reinstate old mappings lib * Update paths to mappings lib * Remove remaining mappings lib
This commit is contained in:
parent
27bc4d2200
commit
5098b5f584
27 changed files with 293 additions and 396 deletions
|
@ -4,9 +4,3 @@ Platform Server Modules
|
|||
Http Server
|
||||
-----------
|
||||
TODO: explain
|
||||
|
||||
Saved Objects Service
|
||||
-----------
|
||||
|
||||
Elasticsearch Service
|
||||
-----------
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`saved objects index mapping constructor includes the pluginId from the extension in the _ error message if defined 1`] = `"Property names _foo registered by plugin abc123 are not allowed to start with an underscore (_)"`;
|
||||
|
||||
exports[`saved objects index mapping constructor throws if any of the new properties start with _ 1`] = `"Property names _foo are not allowed to start with an underscore (_)"`;
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
import { EsMapping, EsMappings, getRootProperties, getRootType } from './lib';
|
||||
import { formatListAsProse } from './utils';
|
||||
|
||||
interface MappingExtension {
|
||||
pluginId?: string;
|
||||
properties: { [key: string]: EsMapping };
|
||||
}
|
||||
|
||||
const DEFAULT_INITIAL_DSL: EsMappings = {
|
||||
rootType: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
};
|
||||
|
||||
export class IndexMappings {
|
||||
private dsl: EsMappings = this.initialDsl;
|
||||
|
||||
constructor(
|
||||
private initialDsl: EsMappings = DEFAULT_INITIAL_DSL,
|
||||
mappingExtensions: MappingExtension[] = []
|
||||
) {
|
||||
// ensure that the dsl can be parsed with getRootProperties() and kin
|
||||
this.setProperties(getRootProperties(this.dsl) || {});
|
||||
|
||||
// extend this.dsl with each extension (which currently come from uiExports.savedObjectMappings)
|
||||
mappingExtensions.forEach(({ properties, pluginId }) => {
|
||||
const rootProperties = getRootProperties(this.dsl);
|
||||
|
||||
const conflicts = Object.keys(properties).filter(key => rootProperties.hasOwnProperty(key));
|
||||
|
||||
const illegal = Object.keys(properties).filter(key => key.startsWith('_'));
|
||||
|
||||
if (conflicts.length) {
|
||||
const props = formatListAsProse(conflicts);
|
||||
const owner = pluginId ? `registered by plugin ${pluginId} ` : '';
|
||||
throw new Error(`Mappings for ${props} ${owner}have already been defined`);
|
||||
}
|
||||
|
||||
if (illegal.length) {
|
||||
const props = formatListAsProse(illegal);
|
||||
const owner = pluginId ? `registered by plugin ${pluginId} ` : '';
|
||||
throw new Error(
|
||||
`Property name${
|
||||
props.length > 1 ? 's' : ''
|
||||
} ${props} ${owner}are not allowed to start with an underscore (_)`
|
||||
);
|
||||
}
|
||||
|
||||
this.setProperties({
|
||||
...rootProperties,
|
||||
...properties,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public getDsl() {
|
||||
return cloneDeep(this.dsl);
|
||||
}
|
||||
|
||||
private setProperties(newProperties: MappingExtension['properties']) {
|
||||
const rootType = getRootType(this.dsl);
|
||||
this.dsl = {
|
||||
...this.dsl,
|
||||
[rootType]: {
|
||||
...this.dsl[rootType],
|
||||
properties: newProperties,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export interface EsMapping {
|
||||
type?: string;
|
||||
dynamic?: true | false | 'strict';
|
||||
properties?: {
|
||||
[key: string]: EsMapping;
|
||||
};
|
||||
fields?: {
|
||||
[key: string]: EsMapping;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EsMappings {
|
||||
// When _doc change enforced, hardcode this to be
|
||||
// '_doc': EsMapping;
|
||||
[rootType: string]: EsMapping;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { formatListAsProse } from './prose';
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts an array of items into a sentence-ready string.
|
||||
*/
|
||||
export function formatListAsProse(list: string[], options = { inclusive: true }) {
|
||||
const { inclusive } = options;
|
||||
|
||||
const count = list.length;
|
||||
const conjunction = inclusive ? 'and' : 'or';
|
||||
|
||||
if (count <= 2) {
|
||||
return list.join(` ${conjunction} `);
|
||||
}
|
||||
|
||||
return list
|
||||
.slice(0, -1)
|
||||
.concat(`${conjunction} ${list[count - 1]}`)
|
||||
.join(', ');
|
||||
}
|
|
@ -23,7 +23,7 @@ import { times, cloneDeep, pick, partition } from 'lodash';
|
|||
import Chance from 'chance';
|
||||
|
||||
import { patchKibanaIndex } from '../patch_kibana_index';
|
||||
import { getRootProperties, getRootType } from '../../../../core/server/saved_objects/mappings';
|
||||
import { getRootProperties, getRootType } from '../../../../server/mappings';
|
||||
|
||||
const chance = new Chance();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import {
|
|||
getTypes,
|
||||
getRootType,
|
||||
getRootProperties
|
||||
} from '../../../core/server/saved_objects/mappings';
|
||||
} from '../../../server/mappings';
|
||||
|
||||
/**
|
||||
* Checks that the root type in the kibana index has all of the
|
||||
|
|
|
@ -36,7 +36,7 @@ import * as Plugins from './plugins';
|
|||
import { indexPatternsMixin } from './index_patterns';
|
||||
import { savedObjectsMixin } from './saved_objects';
|
||||
import { sampleDataMixin } from './sample_data';
|
||||
import { kibanaIndexMappingsMixin } from './saved_objects/mappings';
|
||||
import { kibanaIndexMappingsMixin } from './mappings';
|
||||
import { urlShorteningMixin } from './url_shortening';
|
||||
import { serverExtensionsMixin } from './server_extensions';
|
||||
import { uiMixin } from '../ui';
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`server/mapping/index_mapping constructor includes the pluginId from the extension in the _ error message if defined 1`] = `"Property names _foo registered by plugin abc123 are not allowed to start with an underscore (_)"`;
|
||||
|
||||
exports[`server/mapping/index_mapping constructor throws if any of the new properties start with _ 1`] = `"Property names _foo are not allowed to start with an underscore (_)"`;
|
|
@ -17,7 +17,9 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { IndexMappings } from './index_mappings';
|
||||
export {
|
||||
kibanaIndexMappingsMixin
|
||||
} from './kibana_index_mappings_mixin';
|
||||
|
||||
export {
|
||||
getTypes,
|
90
src/server/mappings/index_mappings.js
Normal file
90
src/server/mappings/index_mappings.js
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { cloneDeep, isPlainObject } from 'lodash';
|
||||
|
||||
import { formatListAsProse } from '../../utils';
|
||||
import { getRootProperties, getRootType } from './lib';
|
||||
|
||||
const DEFAULT_INITIAL_DSL = {
|
||||
rootType: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
};
|
||||
|
||||
export class IndexMappings {
|
||||
constructor(initialDsl = DEFAULT_INITIAL_DSL, mappingExtensions = []) {
|
||||
this._dsl = cloneDeep(initialDsl);
|
||||
if (!isPlainObject(this._dsl)) {
|
||||
throw new TypeError('initial mapping must be an object');
|
||||
}
|
||||
|
||||
// ensure that we have a properties object in the dsl
|
||||
// and that the dsl can be parsed with getRootProperties() and kin
|
||||
this._setProperties(getRootProperties(this._dsl) || {});
|
||||
|
||||
// extend this._dsl with each extension (which currently come from uiExports.savedObjectMappings)
|
||||
mappingExtensions.forEach(({ properties, pluginId }) => {
|
||||
const rootProperties = getRootProperties(this._dsl);
|
||||
|
||||
const conflicts = Object.keys(properties)
|
||||
.filter(key => rootProperties.hasOwnProperty(key));
|
||||
|
||||
const illegal = Object.keys(properties)
|
||||
.filter(key => key.startsWith('_'));
|
||||
|
||||
if (conflicts.length) {
|
||||
const props = formatListAsProse(conflicts);
|
||||
const owner = pluginId ? `registered by plugin ${pluginId} ` : '';
|
||||
throw new Error(
|
||||
`Mappings for ${props} ${owner}have already been defined`
|
||||
);
|
||||
}
|
||||
|
||||
if (illegal.length) {
|
||||
const props = formatListAsProse(illegal);
|
||||
const owner = pluginId ? `registered by plugin ${pluginId} ` : '';
|
||||
throw new Error(
|
||||
`Property name${props.length > 1 ? 's' : ''} ${props} ${owner}are not allowed to start with an underscore (_)`
|
||||
);
|
||||
}
|
||||
|
||||
this._setProperties({
|
||||
...rootProperties,
|
||||
...properties
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getDsl() {
|
||||
return cloneDeep(this._dsl);
|
||||
}
|
||||
|
||||
_setProperties(newProperties) {
|
||||
const rootType = getRootType(this._dsl);
|
||||
this._dsl = {
|
||||
...this._dsl,
|
||||
[rootType]: {
|
||||
...this._dsl[rootType],
|
||||
properties: newProperties
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ import { getRootType } from './lib';
|
|||
|
||||
const chance = new Chance();
|
||||
|
||||
describe('saved objects index mapping', () => {
|
||||
describe('server/mapping/index_mapping', function () {
|
||||
describe('constructor', () => {
|
||||
it('initializes with a default mapping when no args', () => {
|
||||
const mapping = new IndexMappings();
|
||||
|
@ -38,56 +38,54 @@ describe('saved objects index mapping', () => {
|
|||
const mapping = new IndexMappings({
|
||||
foobar: {
|
||||
dynamic: false,
|
||||
properties: {},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
});
|
||||
|
||||
expect(mapping.getDsl()).toEqual({
|
||||
foobar: {
|
||||
dynamic: false,
|
||||
properties: {},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('throws if root type is of type=anything-but-object', () => {
|
||||
expect(() => {
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
new IndexMappings({
|
||||
root: {
|
||||
type: chance.pickone(['string', 'keyword', 'geo_point']),
|
||||
},
|
||||
type: chance.pickone(['string', 'keyword', 'geo_point'])
|
||||
}
|
||||
});
|
||||
}).toThrowError(/not an object/);
|
||||
}).toThrowError(/non-object/);
|
||||
});
|
||||
|
||||
it('throws if root type has no type and no properties', () => {
|
||||
expect(() => {
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
new IndexMappings({
|
||||
root: {},
|
||||
root: {}
|
||||
});
|
||||
}).toThrowError(/not an object/);
|
||||
}).toThrowError(/non-object/);
|
||||
});
|
||||
|
||||
it('initialized root type with properties object if not set', () => {
|
||||
const mapping = new IndexMappings({
|
||||
root: {
|
||||
type: 'object',
|
||||
},
|
||||
type: 'object'
|
||||
}
|
||||
});
|
||||
|
||||
expect(mapping.getDsl()).toEqual({
|
||||
root: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts an array of new extensions that will be added to the mapping', () => {
|
||||
const initialMapping = {
|
||||
x: { properties: {} },
|
||||
x: { properties: {} }
|
||||
};
|
||||
const extensions = [
|
||||
{
|
||||
|
@ -95,12 +93,12 @@ describe('saved objects index mapping', () => {
|
|||
y: {
|
||||
properties: {
|
||||
z: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const mapping = new IndexMappings(initialMapping, extensions);
|
||||
|
@ -110,89 +108,89 @@ describe('saved objects index mapping', () => {
|
|||
y: {
|
||||
properties: {
|
||||
z: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('throws if any of the new properties conflict', () => {
|
||||
const initialMapping = {
|
||||
root: { properties: { foo: { type: 'string' } } },
|
||||
root: { properties: { foo: 'bar' } }
|
||||
};
|
||||
const extensions = [
|
||||
{
|
||||
properties: {
|
||||
foo: { type: 'string' },
|
||||
},
|
||||
},
|
||||
foo: 'bar'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(() => {
|
||||
new IndexMappings(initialMapping, extensions); // tslint:disable-line:no-unused-expression
|
||||
new IndexMappings(initialMapping, extensions);
|
||||
}).toThrowError(/foo/);
|
||||
});
|
||||
|
||||
it('includes the pluginId from the extension in the error message if defined', () => {
|
||||
const initialMapping = {
|
||||
root: { properties: { foo: { type: 'string' } } },
|
||||
root: { properties: { foo: 'bar' } }
|
||||
};
|
||||
const extensions = [
|
||||
{
|
||||
pluginId: 'abc123',
|
||||
properties: {
|
||||
foo: { type: 'string' },
|
||||
},
|
||||
},
|
||||
foo: 'bar'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(() => {
|
||||
new IndexMappings(initialMapping, extensions); // tslint:disable-line:no-unused-expression
|
||||
new IndexMappings(initialMapping, extensions);
|
||||
}).toThrowError(/plugin abc123/);
|
||||
});
|
||||
|
||||
it('throws if any of the new properties start with _', () => {
|
||||
const initialMapping = {
|
||||
root: { properties: { foo: { type: 'string' } } },
|
||||
root: { properties: { foo: 'bar' } }
|
||||
};
|
||||
const extensions = [
|
||||
{
|
||||
properties: {
|
||||
_foo: { type: 'string' },
|
||||
},
|
||||
},
|
||||
_foo: 'bar'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(() => {
|
||||
new IndexMappings(initialMapping, extensions); // tslint:disable-line:no-unused-expression
|
||||
new IndexMappings(initialMapping, extensions);
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
it('includes the pluginId from the extension in the _ error message if defined', () => {
|
||||
const initialMapping = {
|
||||
root: { properties: { foo: { type: 'string' } } },
|
||||
root: { properties: { foo: 'bar' } }
|
||||
};
|
||||
const extensions = [
|
||||
{
|
||||
pluginId: 'abc123',
|
||||
properties: {
|
||||
_foo: { type: 'string' },
|
||||
},
|
||||
},
|
||||
_foo: 'bar'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
expect(() => {
|
||||
new IndexMappings(initialMapping, extensions); // tslint:disable-line:no-unused-expression
|
||||
new IndexMappings(initialMapping, extensions);
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getDsl()', () => {
|
||||
// tests are light because this method is used all over these tests
|
||||
it('returns mapping as es dsl', () => {
|
||||
it('returns mapping as es dsl', function () {
|
||||
const mapping = new IndexMappings();
|
||||
expect(typeof mapping.getDsl()).toBe('object');
|
||||
});
|
|
@ -17,33 +17,34 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { IndexMappings } from '../../../core/server/saved_objects/mappings';
|
||||
import { IndexMappings } from './index_mappings';
|
||||
|
||||
/**
|
||||
* The default mappings used for the Kibana index. This is
|
||||
* extended via uiExports type "mappings". See the Kibana
|
||||
* and Timelion plugins for examples.
|
||||
* The default mappings used for the kibana index. This is
|
||||
* extended via uiExports type "mappings". See the kibana
|
||||
* and timelion plugins for examples.
|
||||
* @type {EsMappingDsl}
|
||||
*/
|
||||
const BASE_SAVED_OBJECT_MAPPINGS = {
|
||||
doc: {
|
||||
dynamic: 'strict',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'keyword',
|
||||
type: 'keyword'
|
||||
},
|
||||
updated_at: {
|
||||
type: 'date',
|
||||
type: 'date'
|
||||
},
|
||||
config: {
|
||||
dynamic: true,
|
||||
properties: {
|
||||
buildNum: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function kibanaIndexMappingsMixin(kbnServer, server) {
|
||||
|
@ -53,14 +54,17 @@ export function kibanaIndexMappingsMixin(kbnServer, server) {
|
|||
);
|
||||
|
||||
/**
|
||||
* Get the mappings that we expect to see in the
|
||||
* Kibana index. Used by the Elasticsearch plugin to create
|
||||
* and update the Kibana index. Also used by the SavedObjectsClient
|
||||
* to determine the properties defined in the mapping and
|
||||
* the "rootType".
|
||||
* Get the mappings dsl that we expect to see in the
|
||||
* Kibana index. Used by the elasticsearch plugin to create
|
||||
* and update the kibana index. Also used by the SavedObjectsClient
|
||||
* to determine the properties defined in the mapping as well as
|
||||
* things like the "rootType".
|
||||
*
|
||||
* See `src/core/server/saved_objects/mappings/lib/index.js` for
|
||||
* helpers useful for reading the EsMappings object.
|
||||
* See `src/server/mappings/lib/index.js` for helpers useful for reading
|
||||
* the EsMappingDsl object.
|
||||
*
|
||||
* @method server.getKibanaIndexMappingsDsl
|
||||
* @returns {EsMappingDsl}
|
||||
*/
|
||||
server.decorate('server', 'getKibanaIndexMappingsDsl', () => {
|
||||
return mappings.getDsl();
|
|
@ -17,35 +17,43 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
// @ts-ignore internal modules are not typed
|
||||
import toPath from 'lodash/internal/toPath';
|
||||
|
||||
import { getRootType } from './get_root_type';
|
||||
import { EsMapping, EsMappings } from './types';
|
||||
|
||||
/**
|
||||
* Recursively read properties from the mapping object of type "object"
|
||||
* until the `path` is resolved.
|
||||
* @param {EsObjectMapping} mapping
|
||||
* @param {Array<string>} path
|
||||
* @return {Objects|undefined}
|
||||
*/
|
||||
function getPropertyMappingFromObjectMapping(
|
||||
mapping: EsMapping,
|
||||
path: string[]
|
||||
): EsMapping | undefined {
|
||||
function getPropertyMappingFromObjectMapping(mapping, path) {
|
||||
const props = mapping && (mapping.properties || mapping.fields);
|
||||
|
||||
if (!props) {
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (path.length > 1) {
|
||||
return getPropertyMappingFromObjectMapping(props[path[0]], path.slice(1));
|
||||
return getPropertyMappingFromObjectMapping(
|
||||
props[path[0]],
|
||||
path.slice(1)
|
||||
);
|
||||
} else {
|
||||
return props[path[0]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapping for a specific property within the root type of the EsMappings.
|
||||
* Get the mapping for a specific property within the root type of the EsMappingsDsl.
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @param {string|Array<string>} path
|
||||
* @return {Object|undefined}
|
||||
*/
|
||||
export function getProperty(mappings: EsMappings, path: string | string[]) {
|
||||
return getPropertyMappingFromObjectMapping(mappings[getRootType(mappings)], toPath(path));
|
||||
export function getProperty(mappings, path) {
|
||||
return getPropertyMappingFromObjectMapping(
|
||||
mappings[getRootType(mappings)],
|
||||
toPath(path)
|
||||
);
|
||||
}
|
|
@ -25,12 +25,12 @@ const MAPPINGS = {
|
|||
foo: {
|
||||
properties: {
|
||||
name: {
|
||||
type: 'text',
|
||||
type: 'text'
|
||||
},
|
||||
description: {
|
||||
type: 'text',
|
||||
},
|
||||
},
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
},
|
||||
bar: {
|
||||
properties: {
|
||||
|
@ -38,18 +38,21 @@ const MAPPINGS = {
|
|||
type: 'text',
|
||||
fields: {
|
||||
box: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function runTest(path: string | string[], mapping: { [key: string]: any }) {
|
||||
expect(getProperty(MAPPINGS, path)).toBe(mapping);
|
||||
function runTest(key, mapping) {
|
||||
expect(typeof key === 'string' || Array.isArray(key)).toBeTruthy();
|
||||
expect(typeof mapping).toBe('object');
|
||||
|
||||
expect(getProperty(MAPPINGS, key)).toBe(mapping);
|
||||
}
|
||||
|
||||
describe('getProperty(mappings, path)', () => {
|
|
@ -18,28 +18,30 @@
|
|||
*/
|
||||
|
||||
import { getRootType } from './get_root_type';
|
||||
import { EsMappings } from './types';
|
||||
|
||||
/**
|
||||
* Get the property mappings for the root type in the EsMappings
|
||||
* Get the property mappings for the root type in the EsMappingsDsl
|
||||
*
|
||||
* If the mappings don't have a root type, or the root type is not
|
||||
* an object type (it's a keyword or something) this function will
|
||||
* throw an error.
|
||||
*
|
||||
* EsMappings objects have the root property names as their
|
||||
* EsPropertyMappings objects have the root property names as their
|
||||
* first level keys which map to the mappings object for each property.
|
||||
* If the property is of type object it too could have a `properties`
|
||||
* key whose value follows the same format.
|
||||
*
|
||||
* This data can be found at `{indexName}.mappings.{typeName}.properties`
|
||||
* in the es indices.get() response.
|
||||
*
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @return {EsPropertyMappings}
|
||||
*/
|
||||
export function getRootProperties(mappings: EsMappings) {
|
||||
export function getRootProperties(mappings) {
|
||||
const mapping = mappings[getRootType(mappings)];
|
||||
|
||||
if (mapping.type !== 'object' && !mapping.properties) {
|
||||
throw new TypeError('Root mapping is not an object type. Unable to get properties.');
|
||||
throw new TypeError('Unable to get property names non-object root mapping');
|
||||
}
|
||||
|
||||
return mapping.properties || {};
|
|
@ -18,10 +18,9 @@
|
|||
*/
|
||||
|
||||
import { getRootProperties } from './get_root_properties';
|
||||
import { EsMappings } from './types';
|
||||
|
||||
/**
|
||||
* Get the property mappings for the root type in the EsMappings
|
||||
* Get the property mappings for the root type in the EsMappingsDsl
|
||||
* where the properties are objects
|
||||
*
|
||||
* If the mappings don't have a root type, or the root type is not
|
||||
|
@ -30,18 +29,19 @@ import { EsMappings } from './types';
|
|||
*
|
||||
* This data can be found at `{indexName}.mappings.{typeName}.properties`
|
||||
* in the es indices.get() response where the properties are objects.
|
||||
*
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @return {EsPropertyMappings}
|
||||
*/
|
||||
export function getRootPropertiesObjects(mappings: EsMappings) {
|
||||
export function getRootPropertiesObjects(mappings) {
|
||||
const rootProperties = getRootProperties(mappings);
|
||||
return Object.entries(rootProperties).reduce(
|
||||
(acc: EsMappings, [key, value]) => {
|
||||
// if value has properties or a type of object, we assume it is an object datatype
|
||||
if (value.properties || value.type === 'object') {
|
||||
acc[key] = value;
|
||||
}
|
||||
return Object.entries(rootProperties).reduce((acc, [key, value]) => {
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as any
|
||||
) as EsMappings;
|
||||
// we consider the existence of the properties or type of object to designate that this is an object datatype
|
||||
if (value.properties || value.type === 'object') {
|
||||
acc[key] = value;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
|
@ -24,17 +24,17 @@ test(`returns single object with properties`, () => {
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
properties: {},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -43,17 +43,17 @@ test(`returns single object with type === 'object'`, () => {
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
type: 'object',
|
||||
},
|
||||
type: 'object'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -62,23 +62,23 @@ test(`returns two objects with properties`, () => {
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
properties: {},
|
||||
properties: {}
|
||||
},
|
||||
bar: {
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
properties: {},
|
||||
properties: {}
|
||||
},
|
||||
bar: {
|
||||
properties: {},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -87,23 +87,23 @@ test(`returns two objects with type === 'object'`, () => {
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object',
|
||||
type: 'object'
|
||||
},
|
||||
bar: {
|
||||
type: 'object',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
type: 'object',
|
||||
type: 'object'
|
||||
},
|
||||
bar: {
|
||||
type: 'object',
|
||||
},
|
||||
type: 'object'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -112,10 +112,10 @@ test(`excludes objects without properties and type of keyword`, () => {
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
|
@ -127,13 +127,13 @@ test(`excludes two objects without properties and type of keyword`, () => {
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'keyword',
|
||||
type: 'keyword'
|
||||
},
|
||||
bar: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
|
@ -145,20 +145,20 @@ test(`includes one object with properties and excludes one object without proper
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
properties: {},
|
||||
properties: {}
|
||||
},
|
||||
bar: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
properties: {},
|
||||
},
|
||||
properties: {}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -167,19 +167,19 @@ test(`includes one object with type === 'object' and excludes one object without
|
|||
rootType: {
|
||||
properties: {
|
||||
foo: {
|
||||
type: 'object',
|
||||
type: 'object'
|
||||
},
|
||||
bar: {
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const result = getRootPropertiesObjects(mappings);
|
||||
expect(result).toEqual({
|
||||
foo: {
|
||||
type: 'object',
|
||||
},
|
||||
type: 'object'
|
||||
}
|
||||
});
|
||||
});
|
|
@ -18,20 +18,20 @@
|
|||
*/
|
||||
|
||||
import { getTypes } from './get_types';
|
||||
import { EsMappings } from './types';
|
||||
|
||||
/**
|
||||
* Get the singular root type in the EsMappings
|
||||
* Get the singular root type in the EsMappingsDsl
|
||||
* object. If there are no types, or there are more
|
||||
* that one type, this function will throw an error.
|
||||
*
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @return {string}
|
||||
*/
|
||||
export function getRootType(mappings: EsMappings) {
|
||||
export function getRootType(mappings) {
|
||||
const allTypes = getTypes(mappings);
|
||||
|
||||
if (allTypes.length !== 1) {
|
||||
throw new TypeError(
|
||||
`Unable to get root type of mappings object with ${allTypes.length} root types.`
|
||||
);
|
||||
throw new TypeError(`Unable to get root type of mappings object with ${allTypes.length} root types.`);
|
||||
}
|
||||
|
||||
return allTypes[0];
|
|
@ -17,11 +17,12 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { EsMappings } from './types';
|
||||
|
||||
/**
|
||||
* Get the names of the types defined in the EsMappings
|
||||
* Get the names of the types defined in the EsMappingsDsl
|
||||
*
|
||||
* @param {EsMappingsDsl} mappings
|
||||
* @return {Array<string>}
|
||||
*/
|
||||
export function getTypes(mappings: EsMappings) {
|
||||
export function getTypes(mappings) {
|
||||
return Object.keys(mappings).filter(type => type !== '_default_');
|
||||
}
|
|
@ -22,4 +22,3 @@ export { getTypes } from './get_types';
|
|||
export { getRootType } from './get_root_type';
|
||||
export { getRootProperties } from './get_root_properties';
|
||||
export { getRootPropertiesObjects } from './get_root_properties_objects';
|
||||
export { EsMapping, EsMappings } from './types';
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { kibanaIndexMappingsMixin } from './kibana_index_mappings_mixin';
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { getRootPropertiesObjects } from '../../../core/server/saved_objects/mappings';
|
||||
import { getRootPropertiesObjects } from '../..//mappings';
|
||||
import { SavedObjectsRepository, ScopedSavedObjectsClientProvider, SavedObjectsRepositoryProvider } from './lib';
|
||||
import { SavedObjectsClient } from './saved_objects_client';
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import uuid from 'uuid';
|
||||
|
||||
import { getRootType } from '../../../../core/server/saved_objects/mappings';
|
||||
import { getRootType } from '../../../mappings';
|
||||
import { getSearchDsl } from './search_dsl';
|
||||
import { trimIdPrefix } from './trim_id_prefix';
|
||||
import { includedFields } from './included_fields';
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { getRootPropertiesObjects } from '../../../../../core/server/saved_objects/mappings';
|
||||
import { getRootPropertiesObjects } from '../../../../mappings';
|
||||
|
||||
/**
|
||||
* Gets the types based on the type. Uses mappings to support
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import Boom from 'boom';
|
||||
|
||||
import { getProperty } from '../../../../../core/server/saved_objects/mappings';
|
||||
import { getProperty } from '../../../../mappings';
|
||||
|
||||
export function getSortingParams(mappings, type, sortField, sortOrder) {
|
||||
if (!sortField) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue