Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripted fields in index pattern #1982

Merged
merged 13 commits into from
Nov 20, 2014
3 changes: 2 additions & 1 deletion src/kibana/components/agg_types/buckets/terms.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ define(function (require) {
},
params: [
{
name: 'field'
name: 'field',
scriptable: true
},
{
name: 'size',
Expand Down
4 changes: 2 additions & 2 deletions src/kibana/components/agg_types/controls/field.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
ng-options="
field as field.name group by field.type for field in aggConfig.vis.indexPattern.fields.raw
| fieldType: aggParam.filterFieldTypes
| filter: { indexed:true }
| orderBy:['type','name']
| filter: { indexed: true }
| orderBy: ['type', 'name']
">
</select>
</div>
2 changes: 1 addition & 1 deletion src/kibana/components/agg_types/param_types/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ define(function (require) {
}

FieldAggParam.prototype.editor = editorHtml;
FieldAggParam.prototype.scriptable = false;
FieldAggParam.prototype.filterFieldTypes = '*';


/**
* Called to serialize values for saving an aggConfig object
*
Expand Down
36 changes: 16 additions & 20 deletions src/kibana/components/courier/courier.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ define(function (require) {
require('modules').get('kibana/courier')
.service('courier', function ($rootScope, Private, Promise, indexPatterns) {
function Courier() {
var courier = this;
var self = this;

var DocSource = Private(require('components/courier/data_source/doc_source'));
var SearchSource = Private(require('components/courier/data_source/search_source'));

var pendingRequests = Private(require('components/courier/_pending_requests'));

var docLooper = courier.docLooper = Private(require('components/courier/looper/doc'));
var searchLooper = courier.searchLooper = Private(require('components/courier/looper/search'));
var docLooper = self.docLooper = Private(require('components/courier/looper/doc'));
var searchLooper = self.searchLooper = Private(require('components/courier/looper/search'));

// expose some internal modules
courier.setRootSearchSource = Private(require('components/courier/data_source/_root_search_source')).set;
self.setRootSearchSource = Private(require('components/courier/data_source/_root_search_source')).set;

courier.SavedObject = Private(require('components/courier/saved_object/saved_object'));
courier.indexPatterns = indexPatterns;
courier.redirectWhenMissing = Private(require('components/courier/_redirect_when_missing'));
self.SavedObject = Private(require('components/courier/saved_object/saved_object'));
self.indexPatterns = indexPatterns;
self.redirectWhenMissing = Private(require('components/courier/_redirect_when_missing'));

courier.DocSource = DocSource;
courier.SearchSource = SearchSource;
self.DocSource = DocSource;
self.SearchSource = SearchSource;

var HastyRefresh = errors.HastyRefresh;
var Abort = errors.Abort;
Expand All @@ -36,7 +36,7 @@ define(function (require) {
*
* @chainable
*/
courier.fetchInterval = function (ms) {
self.fetchInterval = function (ms) {
searchLooper.ms(ms);
return this;
};
Expand All @@ -45,7 +45,7 @@ define(function (require) {
* Start fetching search requests on an interval
* @chainable
*/
courier.start = function () {
self.start = function () {
searchLooper.start();
return this;
};
Expand All @@ -55,7 +55,7 @@ define(function (require) {
* a promise that resembles the success of the fetch completing,
* individual errors are routed to their respective requests.
*/
courier.fetch = function () {
self.fetch = function () {
return searchLooper.run();
};

Expand All @@ -66,7 +66,7 @@ define(function (require) {
*
* @return {boolean}
*/
courier.started = function () {
self.started = function () {
return searchLooper.started();
};

Expand All @@ -77,7 +77,7 @@ define(function (require) {
*
* @chainable
*/
courier.stop = function () {
self.stop = function () {
searchLooper.stop();
return this;
};
Expand All @@ -88,7 +88,7 @@ define(function (require) {
*
* @param {string} type - the type of Source to create
*/
courier.createSource = function (type) {
self.createSource = function (type) {
switch (type) {
case 'doc':
return new DocSource();
Expand All @@ -97,15 +97,11 @@ define(function (require) {
}
};

courier.getFieldsFor = function (indexish) {
return courier.indexPatterns.getFieldsFor(indexish);
};

/**
* Abort all pending requests
* @return {[type]} [description]
*/
courier.close = function () {
self.close = function () {
searchLooper.stop();
docLooper.stop();

Expand Down
5 changes: 2 additions & 3 deletions src/kibana/components/courier/data_source/doc_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@ define(function (require) {
var VersionConflict = errors.VersionConflict;
var RequestFailure = errors.RequestFailure;

_(DocSource).inherits(SourceAbstract);
function DocSource(initialState) {
SourceAbstract.call(this, initialState);
DocSource.Super.call(this, initialState);

// move onResults over to onUpdate, because that makes more sense
this.onUpdate = this.onResults;
this.onResults = void 0;
}

inherits(DocSource, SourceAbstract);

/*****
* PUBLIC API
*****/
Expand Down
82 changes: 41 additions & 41 deletions src/kibana/components/courier/saved_object/saved_object.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ define(function (require) {
if (!_.isObject(config)) config = {};

// save an easy reference to this
var obj = this;
var self = this;

/************
* Initialize config vars
Expand All @@ -39,10 +39,10 @@ define(function (require) {
var customInit = config.init || _.noop;

// optional search source which this object configures
obj.searchSource = config.searchSource && new SearchSource();
self.searchSource = config.searchSource && new SearchSource();

// the id of the document
obj.id = config.id || void 0;
self.id = config.id || void 0;

/**
* Asynchronously initialize this object - will only run
Expand All @@ -51,15 +51,15 @@ define(function (require) {
* @return {Promise}
* @resolved {SavedObject}
*/
obj.init = _.once(function () {
self.init = _.once(function () {
// ensure that the type is defined
if (!type) throw new Error('You must define a type name to use SavedObject objects.');

// tell the docSource where to find the doc
docSource
.index(configFile.kibanaIndex)
.type(type)
.id(obj.id);
.id(self.id);

// check that the mapping for this type is defined
return mappingSetup.isDefined(type)
Expand All @@ -81,56 +81,56 @@ define(function (require) {
})
.then(function () {
// If there is not id, then there is no document to fetch from elasticsearch
if (!obj.id) {
if (!self.id) {
// just assign the defaults and be done
_.assign(obj, defaults);
_.assign(self, defaults);
return hydrateIndexPattern().then(function () {
return afterESResp.call(obj);
return afterESResp.call(self);
});
}

// fetch the object from ES
return docSource.fetch()
.then(function applyESResp(resp) {

obj._source = _.cloneDeep(resp._source);
self._source = _.cloneDeep(resp._source);

if (!resp.found) throw new errors.SavedObjectNotFound(type, obj.id);
if (!resp.found) throw new errors.SavedObjectNotFound(type, self.id);

var meta = resp._source.kibanaSavedObjectMeta || {};
delete resp._source.kibanaSavedObjectMeta;

if (!config.indexPattern && obj._source.indexPattern) {
config.indexPattern = obj._source.indexPattern;
delete obj._source.indexPattern;
if (!config.indexPattern && self._source.indexPattern) {
config.indexPattern = self._source.indexPattern;
delete self._source.indexPattern;
}

// assign the defaults to the response
_.defaults(obj._source, defaults);
_.defaults(self._source, defaults);

// transform the source using _deserializers
_.forOwn(mapping, function ittr(fieldMapping, fieldName) {
if (fieldMapping._deserialize) {
obj._source[fieldName] = fieldMapping._deserialize(obj._source[fieldName], resp, fieldName, fieldMapping);
self._source[fieldName] = fieldMapping._deserialize(self._source[fieldName], resp, fieldName, fieldMapping);
}
});

// Give obj all of the values in _source.fields
_.assign(obj, obj._source);
_.assign(self, self._source);

return Promise.try(function () {
// if we have a searchSource, set it's state based on the searchSourceJSON field
if (obj.searchSource) {
if (self.searchSource) {
var state = {};
try {
state = JSON.parse(meta.searchSourceJSON);
} catch (e) {}
obj.searchSource.set(state);
self.searchSource.set(state);
}
})
.then(hydrateIndexPattern)
.then(function () {
return Promise.cast(afterESResp.call(obj, resp));
return Promise.cast(afterESResp.call(self, resp));
})
.then(function () {
// Any time obj is updated, re-call applyESResp
Expand All @@ -139,11 +139,11 @@ define(function (require) {
});
})
.then(function () {
return customInit.call(obj);
return customInit.call(self);
})
.then(function () {
// return our obj as the result of init()
return obj;
return self;
});
});

Expand All @@ -155,12 +155,12 @@ define(function (require) {
*/
function hydrateIndexPattern() {
return Promise.try(function () {
if (obj.searchSource) {
if (self.searchSource) {

var index = config.indexPattern || obj.searchSource.getOwn('index');
var index = config.indexPattern || self.searchSource.getOwn('index');
if (!index) return;
if (config.clearSavedIndexPattern) {
obj.searchSource.set('index', undefined);
self.searchSource.set('index', undefined);
return;
}

Expand All @@ -169,7 +169,7 @@ define(function (require) {
}

return Promise.resolve(index).then(function (indexPattern) {
obj.searchSource.set('index', indexPattern);
self.searchSource.set('index', indexPattern);
});
}
});
Expand All @@ -182,38 +182,38 @@ define(function (require) {
* @return {Promise}
* @resolved {String} - The id of the doc
*/
obj.save = function () {
self.save = function () {
var body = {};

_.forOwn(mapping, function (fieldMapping, fieldName) {
if (obj[fieldName] != null) {
if (self[fieldName] != null) {
body[fieldName] = (fieldMapping._serialize)
? fieldMapping._serialize(obj[fieldName])
: obj[fieldName];
? fieldMapping._serialize(self[fieldName])
: self[fieldName];
}
});

if (obj.searchSource) {
if (self.searchSource) {
body.kibanaSavedObjectMeta = {
searchSourceJSON: JSON.stringify(_.omit(obj.searchSource.toJSON(), ['sort', 'size']))
searchSourceJSON: JSON.stringify(_.omit(self.searchSource.toJSON(), ['sort', 'size']))
};
}


// Slugify the object id
obj.id = slugifyId(obj.id);
self.id = slugifyId(self.id);

// ensure that the docSource has the current obj.id
docSource.id(obj.id);
// ensure that the docSource has the current self.id
docSource.id(self.id);

// index the document
return obj.saveSource(body);
return self.saveSource(body);
};

obj.saveSource = function (source) {
self.saveSource = function (source) {
return docSource.doIndex(source)
.then(function (id) {
obj.id = id;
self.id = id;
})
.then(function () {
return es.indices.refresh({
Expand All @@ -222,7 +222,7 @@ define(function (require) {
})
.then(function () {
// ensure that the object has the potentially new id
return obj.id;
return self.id;
});
};

Expand All @@ -231,16 +231,16 @@ define(function (require) {
*
* @return {undefined}
*/
obj.destroy = function () {
self.destroy = function () {
docSource.cancelPending();
if (obj.searchSource) obj.searchSource.cancelPending();
if (self.searchSource) self.searchSource.cancelPending();
};

/**
* Delete this object from Elasticsearch
* @return {promise}
*/
obj.delete = function () {
self.delete = function () {
return es.delete({
index: configFile.kibanaIndex,
type: type,
Expand Down
2 changes: 1 addition & 1 deletion src/kibana/components/index_patterns/_field_formats.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* markdown
### Formatting a value
To format a response value, you need to get ahold of the field list, which is usually available at `indexPattern.fields`. When the indexPattern is not available, call `courier.getFieldsFor`. Each field object has a `format` property*, which is an object detailed in [_field_formats.js](https://github.com/elasticsearch/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js).
To format a response value, you need to get ahold of the field list, which is usually available at `indexPattern.fields`. Each field object has a `format` property*, which is an object detailed in [_field_formats.js](https://github.com/elasticsearch/kibana4/blob/master/src/kibana/components/index_patterns/_field_formats.js).
Once you have the field that a response value came from, pass the value to `field.format.convert(value)` and a formatted string representation of the field will be returned.
Expand Down
Loading