Skip to content

Commit

Permalink
backport of #59 #63 #64 #65 along with improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre Padovani committed May 5, 2018
1 parent dedde94 commit 853ba49
Show file tree
Hide file tree
Showing 16 changed files with 240 additions and 85 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
/build/
.idea
.DS_Store
.project
7 changes: 6 additions & 1 deletion public/nested_support/agg_types/buckets/terms.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ Terms.AggTypesBucketsTermsProvider = function(Private) {
routeBasedNotifier.warning('Sorting in Ascending order by Count in Terms aggregations is deprecated');
}
order._count = dir;
if (agg.params.countByParent) {
order['count_' + agg.id] = dir;
} else {
order._count = dir;
}
return;
}

Expand All @@ -192,7 +197,7 @@ Terms.AggTypesBucketsTermsProvider = function(Private) {
}

// if the target aggregation is nested, refer to it by its nested location
if (orderAgg.nestedPath || orderAgg.reverseNested) {
if ((!orderAgg.params.field.nestedPath && agg.params.field.nestedPath) || orderAgg.params.field.nestedPath !== agg.params.field.nestedPath) {
orderAggId = 'nested_' + orderAggId + '>' + orderAggId;
}

Expand Down
4 changes: 4 additions & 0 deletions public/nested_support/agg_types/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import './agg_type';
import './param_types/field';
import './metrics/metric_agg_type';
import './metrics/percentiles';
import './metrics/percentile_ranks';
import './metrics/std_deviation';
import './metrics/top_hit';
import './buckets/terms';
import './buckets/filters';
import './buckets/create_filter/date_histogram';
17 changes: 17 additions & 0 deletions public/nested_support/agg_types/metrics/percentile_ranks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import valuesEditor from 'ui/agg_types/controls/percentile_ranks.html';
import 'ui/number_list';
import { AggTypesMetricsMetricAggTypeProvider } from 'ui/agg_types/metrics/metric_agg_type';
import { AggTypesMetricsGetResponseAggConfigClassProvider } from 'ui/agg_types/metrics/get_response_agg_config_class';
import { RegistryFieldFormatsProvider } from 'ui/registry/field_formats';
import { getPercentileValue } from './percentiles_get_value';
import { uiModules } from 'ui/modules';
import { AggTypesMetricsPercentileRanksProvider } from 'ui/agg_types/metrics/percentile_ranks';

let app = uiModules.get('kibana/courier');

app.run(function(config, Private) {
const PercentileRanksAggType = Private(AggTypesMetricsPercentileRanksProvider);
PercentileRanksAggType.getValue = function (agg, bucket) {
return getPercentileValue(agg, bucket) / 100;
}
});
15 changes: 15 additions & 0 deletions public/nested_support/agg_types/metrics/percentiles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ordinalSuffix } from 'ui/utils/ordinal_suffix';
import percentsEditor from 'ui/agg_types/controls/percentiles.html';
import 'ui/number_list';
import { AggTypesMetricsMetricAggTypeProvider } from 'ui/agg_types/metrics/metric_agg_type';
import { AggTypesMetricsGetResponseAggConfigClassProvider } from 'ui/agg_types/metrics/get_response_agg_config_class';
import { getPercentileValue } from './percentiles_get_value';
import { uiModules } from 'ui/modules';
import { AggTypesMetricsPercentilesProvider } from 'ui/agg_types/metrics/percentiles';

let app = uiModules.get('kibana/courier');

app.run(function(config, Private) {
const PercentilesAggType = Private(AggTypesMetricsPercentilesProvider);
PercentilesAggType.getValue = getPercentileValue;
});
11 changes: 11 additions & 0 deletions public/nested_support/agg_types/metrics/percentiles_get_value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { find } from 'lodash';

export function getPercentileValue(agg, bucket) {
let valueBucket = bucket;
if (bucket['nested_' + agg.parentId]) {
valueBucket = bucket['nested_' + agg.parentId];
}
const values = valueBucket[agg.parentId] && valueBucket[agg.parentId].values;
const percentile = find(values, value => agg.key === value.key);
return percentile ? percentile.value : NaN;
}
18 changes: 18 additions & 0 deletions public/nested_support/agg_types/metrics/std_deviation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import _ from 'lodash';
import { AggTypesMetricsMetricAggTypeProvider } from 'ui/agg_types/metrics/metric_agg_type';
import { AggTypesMetricsGetResponseAggConfigClassProvider } from 'ui/agg_types/metrics/get_response_agg_config_class';
import { uiModules } from 'ui/modules';
import { AggTypesMetricsStdDeviationProvider } from 'ui/agg_types/metrics/std_deviation';

let app = uiModules.get('kibana/courier');

app.run(function(config, Private) {
const StdDeviationAggType = Private(AggTypesMetricsStdDeviationProvider);
StdDeviationAggType.getValue = function (agg, bucket) {
let valueBucket = bucket;
if (bucket['nested_' + agg.parentId]) {
valueBucket = bucket['nested_' + agg.parentId];
}
return _.get(valueBucket[agg.parentId], agg.valProp());
};
});
51 changes: 51 additions & 0 deletions public/nested_support/agg_types/metrics/top_hit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import _ from 'lodash';
import { AggTypesMetricsMetricAggTypeProvider } from 'ui/agg_types/metrics/metric_agg_type';
import topSortEditor from 'ui/agg_types/controls/top_sort.html';
import aggregateAndSizeEditor from 'ui/agg_types/controls/top_aggregate_and_size.html';
import { uiModules } from 'ui/modules';
import { AggTypesMetricsTopHitProvider } from 'ui/agg_types/metrics/top_hit';

let app = uiModules.get('kibana/courier');

app.run(function(config, Private) {
const TopHitType = Private(AggTypesMetricsTopHitProvider);
TopHitType.getValue = function (agg, bucket) {
let valueBucket = bucket;
if (bucket['nested_' + agg.parentId]) {
valueBucket = bucket['nested_' + agg.parentId];
}
const hits = _.get(valueBucket, `${agg.id}.hits.hits`);
if (!hits || !hits.length) {
return null;
}
const path = agg.params.field.name;

let values = _(hits).map(hit => {
return path === '_source' ? hit._source : agg.vis.indexPattern.flattenHit(hit, true)[path];
})
.flatten()
.value();

if (values.length === 1) {
values = values[0];
}

if (_.isArray(values)) {
if (!_.compact(values).length) {
return null;
}
switch (agg.params.aggregate.val) {
case 'max':
return _.max(values);
case 'min':
return _.min(values);
case 'sum':
return _.sum(values);
case 'average':
return _.sum(values) / values.length;
}
}
return values;
}
});

2 changes: 1 addition & 1 deletion public/nested_support/doc_view/structure.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<td style="padding-left: 15px" colspan="2" style="width: 100%">
<div id="expanded-data" ng-if="visible(field + '_', pos)" >
<div ng-repeat="(pos, subObj) in (subObj ? subObj[field] : flattened[field]) track by $index"
ng-init="subFormattedArray = (subFormatted ? subFormatted[field] : formatted[field]); fieldPrefix = field" style="border-style: ridge;">
ng-init="subFormattedArray = (subFormatted ? subFormatted[field] : formatted[field]); fieldPrefix = field" style="border-style: ridge; margin-top: 10px; border-width: 2px">
<table class="table table-condensed table-bordered">
<tbody ng-repeat="(field, value) in subObj track by field" ng-if="true"
onLoad="subFormatted = subFormattedArray[pos]" ng-include="'tree_item.html'">
Expand Down
140 changes: 66 additions & 74 deletions public/nested_support/doc_view/structure.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,80 @@
import _ from 'lodash';
import {DocViewsRegistryProvider} from 'ui/registry/doc_views';
import { uiModules } from 'ui/modules';

import tableHtml from './structure.html';

DocViewsRegistryProvider.register(function () {
return {
title: 'Structure',
order: 5,
directive: {
template: tableHtml,
scope: {
hit: '=',
indexPattern: '=',
filter: '=',
columns: '=',
onAddColumn: '=',
onRemoveColumn: '='
},
controller: function ($scope) {
$scope.mapping = $scope.indexPattern.fields.byName;
$scope.flattened = $scope.indexPattern.flattenHit($scope.hit);
$scope.formatted = $scope.indexPattern.formatHit($scope.hit, true);
$scope.fields = _.keys($scope.flattened).sort();
$scope.visible = {};

$scope.canToggleColumns = function canToggleColumn() {
return (
_.isFunction($scope.onAddColumn)
&& _.isFunction($scope.onRemoveColumn)
);
};
uiModules.get('kibana')
.run(function (config, Private) {
const docViews = Private(DocViewsRegistryProvider);
docViews.byName.Table.directive.template = tableHtml;
docViews.byName.Table.directive.controller = structureController;
});

$scope.toggleColumn = function toggleColumn(columnName) {
if ($scope.columns.includes(columnName)) {
$scope.onRemoveColumn(columnName);
} else {
$scope.onAddColumn(columnName);
}
};
function structureController($scope) {
$scope.mapping = $scope.indexPattern.fields.byName;
$scope.flattened = $scope.indexPattern.flattenHit($scope.hit, false);
$scope.formatted = $scope.indexPattern.formatHit($scope.hit, true);
$scope.fields = _.keys($scope.flattened).sort();
$scope.visible = {};

$scope.visible = function (field, pos) {
let key = field;
if (pos !== undefined) {
key += pos;
}
return $scope.visible[key];
};
$scope.canToggleColumns = function canToggleColumn() {
return (
_.isFunction($scope.onAddColumn)
&& _.isFunction($scope.onRemoveColumn)
);
};

$scope.toggleVisible = function (field, pos) {
let key = field;
if (pos !== undefined) {
key += pos;
}
if ($scope.visible[key] === undefined) {
$scope.visible[key] = key;
} else {
$scope.visible[key] = undefined;
}
};
$scope.toggleColumn = function toggleColumn(columnName) {
if ($scope.columns.includes(columnName)) {
$scope.onRemoveColumn(columnName);
} else {
$scope.onAddColumn(columnName);
}
};

$scope.showArrayInObjectsWarning = function (row, field) {
let value = $scope.flattened[field];
if (row !== undefined) {
value = row[field];
}
return _.isArray(value) && typeof value[0] === 'object';
};
$scope.visible = function (field, pos) {
let key = field;
if (pos !== undefined) {
key += pos;
}
return $scope.visible[key];
};

$scope.rowSummary = function (row, fieldName, pos) {
const partials = $scope.hit.$$_partialFormatted;
let key = fieldName;
let text = '';
if (pos !== undefined) {
key += pos;
}
if (partials && partials[key] != null) {
text = partials[key];
} else {
text = partials[key] = $scope.indexPattern._legacyFormatField($scope.hit, fieldName);
}
$scope.toggleVisible = function (field, pos) {
let key = field;
if (pos !== undefined) {
key += pos;
}
if ($scope.visible[key] === undefined) {
$scope.visible[key] = key;
} else {
$scope.visible[key] = undefined;
}
};

$scope.showArrayInObjectsWarning = function (row, field) {
let value = $scope.flattened[field];
if (row !== undefined) {
value = row[field];
}
return _.isArray(value) && typeof value[0] === 'object';
};

return _.trunc(text, {'length': 200});
};
}
$scope.rowSummary = function (row, fieldName, pos) {
const partials = $scope.hit.$$_partialFormatted;
let key = fieldName;
let text = '';
if (pos !== undefined) {
key += pos;
}
if (partials && partials[key] != null) {
text = partials[key];
} else {
text = partials[key] = $scope.indexPattern.formatField($scope.hit, fieldName);
}

return _.trunc(text, {'length': 200});
};
});
}
3 changes: 2 additions & 1 deletion public/nested_support/filter_manager/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './filter_manager';
import './lib/phrase';
import './lib/range';
import './lib/range';
import './lib/exists';
27 changes: 27 additions & 0 deletions public/nested_support/filter_manager/lib/exists.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as existsLib from 'ui/filter_manager/lib/exists';

existsLib.buildExistsFilter = function(field, indexPattern) {
if (field.nestedPath) {
return {
meta: {
index: indexPattern.id
},
nested: {
path: field.nestedPath,
query: {
exists: {
field: field.name
}
}
}
};
}
return {
meta: {
index: indexPattern.id
},
exists: {
field: field.name
}
};
};
8 changes: 6 additions & 2 deletions public/nested_support/index_patterns/_flatten_hit.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,12 @@ export function IndexPatternsNestedFlattenHitProvider(config) {
}

return function flattenHitWrapper(indexPattern) {
return function cachedFlatten(hit, deep = false) {
return hit.$$_flattened || (hit.$$_flattened = flattenHit(indexPattern, hit, deep));
return function cachedFlatten(hit, deep = true) {
if (deep) {
return hit.$$_flattened_deep || (hit.$$_flattened_deep = flattenHit(indexPattern, hit, deep));
} else {
return hit.$$_flattened || (hit.$$_flattened = flattenHit(indexPattern, hit, deep));
}
};
};
}
6 changes: 3 additions & 3 deletions public/nested_support/index_patterns/_format_hit.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function nestedFormatHit(indexPattern, defaultFormat) {
function convert(hit, val, fieldName, recurse) {
const field = indexPattern.fields.byName[fieldName];
if (!field) {
if (val.constructor === Array && recurse) {
if (val && val.constructor === Array && recurse) {
let pArr = [];
_.forEach(val, function (item) {
let pStore = {};
Expand Down Expand Up @@ -41,7 +41,7 @@ export function nestedFormatHit(indexPattern, defaultFormat) {
const partials = (recurse ? hit.$$_partialStructured : hit.$$_partialFormatted) || (recurse ? hit.$$_partialStructured = {}: hit.$$_partialFormatted = {});
const cache = (recurse ? hit.$$_structured = {} : hit.$$_formatted = {});

_.forOwn(indexPattern.flattenHit(hit), function (val, fieldName) {
_.forOwn(indexPattern.flattenHit(hit, false), function (val, fieldName) {
// sync the formatted and partial cache
// const formatted = partials[fieldName] == null ? convert(hit, val, fieldName) : partials[fieldName];
const formatted = partials[fieldName] == null ? convert(hit, val, fieldName, recurse) : partials[fieldName];
Expand All @@ -61,7 +61,7 @@ export function nestedFormatHit(indexPattern, defaultFormat) {
partials = hit.$$_partialFormatted = {};
}

const val = fieldName === '_source' ? hit._source : indexPattern.flattenHit(hit)[fieldName];
const val = fieldName === '_source' ? hit._source : indexPattern.flattenHit(hit, false)[fieldName];
return partials[fieldName] = convert(hit, val, fieldName, false);
};

Expand Down
Loading

0 comments on commit 853ba49

Please sign in to comment.