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

Nested support 4.6 #6

Open
wants to merge 3 commits into
base: 4.6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"imports-loader": "0.6.4",
"jade": "1.11.0",
"jade-loader": "0.7.1",
"jison": "0.4.17",
"joi": "6.6.1",
"jquery": "2.1.4",
"js-yaml": "3.4.1",
Expand Down
2 changes: 1 addition & 1 deletion src/optimize/BaseOptimizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class BaseOptimizer {
return {
context: fromRoot('.'),
entry: this.bundles.toWebpackEntries(),

node: {fs: 'empty'},
devtool: this.sourceMaps,
profile: this.profile || false,

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/elasticsearch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module.exports = function ({ Plugin }) {
key: string()
}).default(),
apiVersion: string().default('2.0'),
engineVersion: string().valid('^2.4.0').default('^2.4.0')
engineVersion: string().valid('>=1.7.0 || <5.0.0').default('>=1.7.0 || <5.0.0')
}).default();
},

Expand Down
114 changes: 109 additions & 5 deletions src/ui/public/Vis/AggConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,32 @@ define(function (require) {
* @return {void|Object} - if the config has a dsl representation, it is
* returned, else undefined is returned
*/
AggConfig.prototype.toDsl = function () {
AggConfig.prototype.toDsl = function (prevNestedPath) {
if (this.type.hasNoDsl) return;
let output = this.write();
let output;
if (this.params.orderAgg) {
let reverseNested = false;
let nestedPath = (this.params.orderAgg.params.field ? this.params.orderAgg.params.field.nestedPath : undefined);
let dsl;

if (prevNestedPath !== undefined) {
if (nestedPath === undefined || (nestedPath !== prevNestedPath && prevNestedPath.startsWith(nestedPath))) {
reverseNested = true;
}
}

if (nestedPath !== undefined) {
if (nestedPath === prevNestedPath) {
nestedPath = undefined;
} else {
prevNestedPath = nestedPath;
}
}
this.params.orderAgg.nestedPath = nestedPath;
this.params.orderAgg.reverseNested = reverseNested;
}

output = this.write();

let configDsl = {};
configDsl[this.type.dslName || this.type.name] = output.params;
Expand All @@ -207,13 +230,91 @@ define(function (require) {
if (output.subAggs) {
let subDslLvl = configDsl.aggs || (configDsl.aggs = {});
output.subAggs.forEach(function nestAdhocSubAggs(subAggConfig) {
subDslLvl[subAggConfig.id] = subAggConfig.toDsl();
let reverseNested = false;
let nestedPath = (subAggConfig.params.field ? subAggConfig.params.field.nestedPath : undefined);
let dsl;

if (prevNestedPath !== undefined) {
if (nestedPath === undefined || (nestedPath !== prevNestedPath && prevNestedPath.startsWith(nestedPath))) {
reverseNested = true;
}
}

if (nestedPath !== undefined) {
if (nestedPath === prevNestedPath) {
nestedPath = undefined;
} else {
prevNestedPath = nestedPath;
}
}

subAggConfig.toDslNested(subDslLvl, nestedPath, reverseNested);
});
}

return configDsl;
};

/**
* Convert this aggConfig to its dsl syntax, handling the case that the
* config is nested. If it is not nested, this is equivalent to:
* `destination[this.id] = this.toDsl()`. If it is nested, the value of
* `destination['nested_' + this.id]` reflects the nested structure, and
* the original dsl exists at `destination['nested_' + this.id][this.id]`.
*
* @param destination The destination object in which to emplace the DSL
* under the appropriate key.
* @returns {void|Object} The original result of `this.toDsl()`, regardless
* of whether this aggregation is nested.
*/
AggConfig.prototype.toDslNested = function (destination, nestedPath, reverseNested) {
let id = this.id;
let dsl = this.toDsl(nestedPath);
let result = dsl; // save the original dsl to return later

if (this.params.countByParent) {
let countId = 'count_' + this.id;
let aggsKey = 'aggs';
let countAgg = {};
if (dsl.aggs) {
countAgg = dsl.aggs;
}
countAgg[countId] = {
reverse_nested : {}
};
dsl[aggsKey] = countAgg;
}


if (nestedPath || reverseNested) {
// save the current dsl as a sub-agg of the nested agg
let aggs = {};
aggs[id] = dsl;
if (reverseNested) {
let reverseNestedDsl = {};
// when reverse nesting, the path is optional
if (nestedPath) {
reverseNestedDsl.path = nestedPath;
}
id = 'nested_' + this.id;
dsl = {
reverse_nested: reverseNestedDsl,
aggs: aggs
};
} else if (nestedPath) {
id = 'nested_' + this.id;
dsl = {
nested: {
path: nestedPath
},
aggs: aggs
};
}
}
// apply the change to the destination
destination[id] = dsl;
return result;
};

AggConfig.prototype.toJSON = function () {
let self = this;
let params = self.params;
Expand Down Expand Up @@ -250,7 +351,10 @@ define(function (require) {
return this.type.getResponseAggs(this) || [this];
};

AggConfig.prototype.getValue = function (bucket) {
AggConfig.prototype.getValue = function (id, bucket) {
if (bucket['count_' + id]) {
return this.type.getValue(this, bucket['count_' + id]);
}
return this.type.getValue(this, bucket);
};

Expand Down
53 changes: 40 additions & 13 deletions src/ui/public/Vis/AggConfigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ define(function (require) {

AggConfigs.prototype.toDsl = function () {
let dslTopLvl = {};
let dslLvlCursor;
let dslLvlCursor = dslTopLvl; // start at the top level;
let nestedMetrics;
let prevNestedPath;

if (this.vis.isHierarchical()) {
// collect all metrics, and filter out the ones that we won't be copying
Expand All @@ -71,20 +72,33 @@ define(function (require) {
return !config.type.hasNoDsl;
})
.forEach(function nestEachConfig(config, i, list) {
if (!dslLvlCursor) {
// start at the top level
dslLvlCursor = dslTopLvl;
} else {
let prevConfig = list[i - 1];
let prevDsl = dslLvlCursor[prevConfig.id];
let reverseNested = false;
let nestedPath = (config.params.field ? config.params.field.nestedPath : undefined);
let dsl;

if (config.params.filters) {
config.params.filters.forEach(function findNestedPath(filter) {
if (filter.input.query.nested) {
nestedPath = filter.input.query.nested.path;
}
});
}

// advance the cursor and nest under the previous agg, or
// put it on the same level if the previous agg doesn't accept
// sub aggs
dslLvlCursor = prevDsl.aggs || dslLvlCursor;
if (prevNestedPath !== undefined) {
if (nestedPath === undefined || (nestedPath !== prevNestedPath && prevNestedPath.startsWith(nestedPath))) {
reverseNested = true;
}
}

if (nestedPath !== undefined) {
if (nestedPath === prevNestedPath) {
nestedPath = undefined;
} else {
prevNestedPath = nestedPath;
}
}
dsl = config.toDslNested(dslLvlCursor, nestedPath, reverseNested);

let dsl = dslLvlCursor[config.id] = config.toDsl();
let subAggs;

if (config.schema.group === 'buckets' && i < list.length - 1) {
Expand All @@ -94,9 +108,22 @@ define(function (require) {

if (subAggs && nestedMetrics) {
nestedMetrics.forEach(function (agg) {
subAggs[agg.config.id] = agg.dsl;
if (typeof agg === AggConfig) {
agg.toDslNested(subAggs);
} else {
subAggs[agg.config.id] = agg.dsl;
}
});
} else {
if (dsl.aggs === undefined) {
prevNestedPath = undefined;
}
}

// advance the cursor and nest under the previous agg, or
// put it on the same level if the previous agg doesn't accept
// sub aggs
dslLvlCursor = dsl.aggs || dslLvlCursor;
});

return dslTopLvl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ define(function (require) {
}

// iterate through all the buckets
_.each(extractBuckets(data[agg.id], agg), function (bucket) {
_.each(extractBuckets(data[agg.id] || data['nested_' + agg.id][agg.id]), function (bucket) {

let _record = _.flattenDeep([record, bucket.key]);
_.each(metrics, function (metric) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ define(function (require) {
let aggConfigResult = new AggConfigResult(
agg,
parent && parent.aggConfigResult,
metric.getValue(bucket),
metric.getValue(agg.id, bucket),
agg.getKey(bucket)
);

Expand All @@ -29,6 +29,9 @@ define(function (require) {
// transform it as well. This is where the recursion happens.
if (agg._next) {
let nextBucket = bucket[agg._next.id];
if (bucket['nested_' + agg._next.id] !== undefined) {
nextBucket = bucket['nested_' + agg._next.id][agg._next.id];
}
if (nextBucket && nextBucket.buckets) {
branch.children = transformAggregation(agg._next, metric, nextBucket, branch);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ define(function (require) {
});

return function (vis, resp) {
// Create a refrenece to the buckets
// Create a reference to the buckets
let buckets = vis.aggs.bySchemaGroup.buckets;


Expand Down Expand Up @@ -50,7 +50,7 @@ define(function (require) {
}

let firstAgg = buckets[0];
let aggData = resp.aggregations[firstAgg.id];
let aggData = resp.aggregations[firstAgg.id] || resp.aggregations['nested_' + firstAgg.id][firstAgg.id];

if (!firstAgg._next && firstAgg.schema.name === 'split') {
notify.error('Splitting charts without splitting slices is not supported. Pretending that we are just splitting slices.');
Expand All @@ -68,7 +68,7 @@ define(function (require) {
// map the split aggregations into rows.
let rows = _.map(extractBuckets(aggData, firstAgg), function (bucket) {
let agg = firstAgg._next;
let split = buildSplit(agg, metric, bucket[agg.id]);
let split = buildSplit(agg, metric, bucket[agg.id] || resp.aggregations['nested_' + firstAgg.id][firstAgg.id]);
// Since splits display labels we need to set it.
split.label = firstAgg.fieldFormatter()(agg.getKey(bucket));

Expand Down
15 changes: 9 additions & 6 deletions src/ui/public/agg_response/tabify/tabify.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ define(function (require) {
doc_count: esResponse.hits.total
});

collectBucket(write, topLevelBucket);
collectBucket(write, undefined, topLevelBucket);

return write.response();
}
Expand All @@ -28,22 +28,25 @@ define(function (require) {
* @param {undefined|string} key - the key where the bucket was found
* @returns {undefined}
*/
function collectBucket(write, bucket, key) {
function collectBucket(write, id, bucket, key) {
let agg = write.aggStack.shift();

switch (agg.schema.group) {
case 'buckets':
let buckets = new Buckets(bucket[agg.id]);
if (bucket['nested_' + agg.id] !== undefined) {
buckets = new Buckets(bucket['nested_' + agg.id][agg.id]);
}
if (buckets.length) {
let splitting = write.canSplit && agg.schema.name === 'split';
if (splitting) {
write.split(agg, buckets, function forEachBucket(subBucket, key) {
collectBucket(write, subBucket, agg.getKey(subBucket), key);
collectBucket(write, agg.id, subBucket, agg.getKey(subBucket, key));
});
} else {
buckets.forEach(function (subBucket, key) {
write.cell(agg, agg.getKey(subBucket, key), function () {
collectBucket(write, subBucket, agg.getKey(subBucket, key));
collectBucket(write, agg.id, subBucket, agg.getKey(subBucket, key));
});
});
}
Expand All @@ -61,14 +64,14 @@ define(function (require) {
}
break;
case 'metrics':
let value = agg.getValue(bucket);
let value = agg.getValue(id, bucket);
write.cell(agg, value, function () {
if (!write.aggStack.length) {
// row complete
write.row();
} else {
// process the next agg at this same level
collectBucket(write, bucket, key);
collectBucket(write, agg.id, bucket, key);
}
});
break;
Expand Down
13 changes: 13 additions & 0 deletions src/ui/public/agg_types/AggType.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ define(function (require) {
});
}

// always append the nested-path param
this.params.push({
name: 'nested',
type: 'nested',
advanced: true
});

this.params.push({
name: 'countByParent',
type: 'boolean',
write: _.noop
});

this.params = new AggParams(this.params);
}

Expand Down
Loading