First pass at adding support for fields that are part of an object

This commit is contained in:
Matthew Bargar 2016-01-05 16:45:08 -05:00
parent d4e85bc7da
commit fe296b4b36
8 changed files with 123 additions and 88 deletions

View file

@ -1,52 +0,0 @@
const createMappingFromPatternField = require('../create_mapping_from_pattern_field');
const expect = require('expect.js');
const _ = require('lodash');
let testField;
describe('createMappingFromPatternField', function () {
beforeEach(function () {
testField = {
'name': 'ip',
'type': 'ip',
'count': 2,
'scripted': false
};
});
it('should throw an error if the argument is empty', function () {
expect(createMappingFromPatternField).to.throwException(/argument must not be empty/);
});
it('should not modify the original argument', function () {
const testFieldClone = _.cloneDeep(testField);
const mapping = createMappingFromPatternField(testField);
expect(mapping).to.not.be(testField);
expect(_.isEqual(testField, testFieldClone)).to.be.ok();
});
it('should remove kibana properties that are not valid for ES field mappings', function () {
const mapping = createMappingFromPatternField(testField);
expect(mapping).to.not.have.property('name');
expect(mapping).to.not.have.property('count');
expect(mapping).to.not.have.property('scripted');
expect(mapping).to.not.have.property('indexed');
expect(mapping).to.not.have.property('analyzed');
});
it('should set doc_values and indexed status based on the relevant kibana properties if they exist', function () {
testField.indexed = true;
testField.analyzed = false;
testField.doc_values = true;
let mapping = createMappingFromPatternField(testField);
expect(mapping).to.have.property('doc_values', true);
expect(mapping).to.have.property('index', 'not_analyzed');
testField.analyzed = true;
mapping = createMappingFromPatternField(testField);
expect(mapping).to.have.property('index', 'analyzed');
});
});

View file

@ -0,0 +1,69 @@
const createMappingsFromPatternFields = require('../create_mappings_from_pattern_fields');
const expect = require('expect.js');
const _ = require('lodash');
let testFields;
describe('createMappingsFromPatternFields', function () {
beforeEach(function () {
testFields = [
{
'name': 'ip',
'type': 'ip',
'count': 2,
'scripted': false
},
{
'name': 'geo.coordinates',
'type': 'geo_point',
'count': 0,
'scripted': false
}
];
});
it('should throw an error if the argument is empty', function () {
expect(createMappingsFromPatternFields).to.throwException(/argument must not be empty/);
});
it('should not modify the original argument', function () {
const testFieldClone = _.cloneDeep(testFields);
const mappings = createMappingsFromPatternFields(testFields);
expect(mappings.ip).to.not.be(testFields[0]);
expect(_.isEqual(testFields, testFieldClone)).to.be.ok();
});
it('should remove kibana properties that are not valid for ES field mappings', function () {
const mappings = createMappingsFromPatternFields(testFields);
expect(mappings.ip).to.not.have.property('name');
expect(mappings.ip).to.not.have.property('count');
expect(mappings.ip).to.not.have.property('scripted');
expect(mappings.ip).to.not.have.property('indexed');
expect(mappings.ip).to.not.have.property('analyzed');
});
it('should set doc_values and indexed status based on the relevant kibana properties if they exist', function () {
testFields[0].indexed = true;
testFields[0].analyzed = false;
testFields[0].doc_values = true;
let mappings = createMappingsFromPatternFields(testFields);
expect(mappings.ip).to.have.property('doc_values', true);
expect(mappings.ip).to.have.property('index', 'not_analyzed');
testFields[0].analyzed = true;
mappings = createMappingsFromPatternFields(testFields);
expect(mappings.ip).to.have.property('index', 'analyzed');
});
it('should handle nested fields', function () {
let mappings = createMappingsFromPatternFields(testFields);
expect(mappings).to.have.property('geo');
expect(mappings.geo).to.have.property('properties');
expect(mappings.geo.properties).to.have.property('coordinates');
expect(_.isEqual(mappings.geo.properties.coordinates, {type: 'geo_point'}));
});
});

View file

@ -1,29 +0,0 @@
const _ = require('lodash');
// Creates an ES field mapping from a single field object in a kibana index pattern
module.exports = function createMappingFromPatternField(field) {
if (_.isEmpty(field)) {
throw new Error('argument must not be empty');
}
const mapping = _.cloneDeep(field);
delete mapping.name;
delete mapping.count;
delete mapping.scripted;
delete mapping.indexed;
delete mapping.analyzed;
if (field.indexed === false) {
mapping.index = 'no';
}
else {
if (field.analyzed === false) {
mapping.index = 'not_analyzed';
}
else if (field.analyzed === true) {
mapping.index = 'analyzed';
}
}
return mapping;
};

View file

@ -0,0 +1,36 @@
const _ = require('lodash');
// Creates an ES field mapping from a single field object in a kibana index pattern
module.exports = function createMappingsFromPatternFields(fields) {
if (_.isEmpty(fields)) {
throw new Error('argument must not be empty');
}
const mappings = {};
_.forEach(fields, function (field) {
const mapping = _.cloneDeep(field);
delete mapping.name;
delete mapping.count;
delete mapping.scripted;
delete mapping.indexed;
delete mapping.analyzed;
if (field.indexed === false) {
mapping.index = 'no';
}
else {
if (field.analyzed === false) {
mapping.index = 'not_analyzed';
}
else if (field.analyzed === true) {
mapping.index = 'analyzed';
}
}
_.set(mappings, field.name.replace('.', '.properties.'), mapping);
});
return mappings;
};

View file

@ -4,7 +4,7 @@ const {templateToPattern, patternToTemplate} = require('../../../lib/convert_pat
const indexPatternSchema = require('../../../lib/schemas/resources/index_pattern_schema');
const handleESError = require('../../../lib/handle_es_error');
const { convertToCamelCase } = require('../../../lib/case_conversion');
const createMappingFromPatternField = require('../../../lib/create_mapping_from_pattern_field');
const createMappingsFromPatternFields = require('../../../lib/create_mappings_from_pattern_fields');
const castMappingType = require('../../../lib/cast_mapping_type');
module.exports = function registerPost(server) {
@ -42,11 +42,7 @@ module.exports = function registerPost(server) {
}
});
const mappings = _(indexPattern.fields)
.reject('scripted')
.indexBy('name')
.mapValues(createMappingFromPatternField)
.value();
const mappings = createMappingsFromPatternFields(_.reject(indexPattern.fields, 'scripted'));
_.forEach(indexPattern.fields, function (field) {
field.type = castMappingType(field.type);

View file

@ -52,6 +52,7 @@ module.exports = function (grunt) {
args: [
'--server.port=' + uiConfig.servers.kibana.port,
'--env.name=development',
//remember to remove this
'--server.xsrf.disableProtection=true',
'--elasticsearch.url=' + format(uiConfig.servers.elasticsearch),
'--logging.json=false'

View file

@ -80,7 +80,8 @@ define(function (require) {
});
});
bdd.it('should create index template default mappings based on the info in the kibana index pattern', function createTemplate() {
bdd.it('should create index template with _default_ mappings based on the info in the kibana index pattern',
function createTemplate() {
return request.post('/kibana/index_patterns')
.send(createTestData().indexPattern)
.expect(201)
@ -93,6 +94,15 @@ define(function (require) {
expect(_.isEqual(mappings['@timestamp'], {index: 'not_analyzed', type: 'date', doc_values: true})).to.be.ok();
expect(_.isEqual(mappings.agent, {index: 'analyzed', type: 'string', doc_values: false})).to.be.ok();
expect(_.isEqual(mappings.bytes, {index: 'not_analyzed', type: 'long', doc_values: true})).to.be.ok();
expect(_.isEqual(mappings.geo, {
properties: {
coordinates: {
index: 'not_analyzed',
type: 'geo_point',
doc_values: true
}
}
})).to.be.ok();
});
});
});

View file

@ -27,6 +27,10 @@ module.exports = function createTestData() {
}, {
'name': 'bytes',
'type': 'long'
},
{
'name': 'geo.coordinates',
'type': 'geo_point'
}]
}
}