Skip to content

Commit

Permalink
fix other buket
Browse files Browse the repository at this point in the history
  • Loading branch information
flash1293 committed Nov 4, 2021
1 parent 6ca8edb commit 50df207
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@

import { isNumber, keys, values, find, each, cloneDeep, flatten } from 'lodash';
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { buildExistsFilter, buildPhrasesFilter, buildQueryFromFilters } from '@kbn/es-query';
import {
buildExistsFilter,
buildPhrasesFilter,
buildQueryFromFilters,
Filter,
} from '@kbn/es-query';
import { AggGroupNames } from '../agg_groups';
import { IAggConfigs } from '../agg_configs';
import { IBucketAggConfig } from './bucket_agg_type';
Expand Down Expand Up @@ -200,12 +205,16 @@ export const buildOtherBucketAgg = (
return;
}

const hasScriptedField = !!aggWithOtherBucket.params.field.scripted;
const hasScriptedField = !!aggWithOtherBucket.params.field?.scripted;
const hasMissingBucket = !!aggWithOtherBucket.params.missingBucket;
const hasMissingBucketKey = agg.buckets.some(
(bucket: { key: string }) => bucket.key === '__missing__'
);
if (!hasScriptedField && (!hasMissingBucket || hasMissingBucketKey)) {
if (
aggWithOtherBucket.params.field &&
!hasScriptedField &&
(!hasMissingBucket || hasMissingBucketKey)
) {
filters.push(
buildExistsFilter(
aggWithOtherBucket.params.field,
Expand All @@ -217,7 +226,7 @@ export const buildOtherBucketAgg = (
// create not filters for all the buckets
each(agg.buckets, (bucket) => {
if (bucket.key === '__missing__') return;
const filter = currentAgg.createFilter(bucket.key);
const filter = currentAgg.createFilter(currentAgg.getKey(bucket, bucket.key));
filter.meta.negate = true;
filters.push(filter);
});
Expand Down Expand Up @@ -245,7 +254,12 @@ export const mergeOtherBucketAggResponse = (
response: estypes.SearchResponse<any>,
otherResponse: any,
otherAgg: IBucketAggConfig,
requestAgg: Record<string, any>
requestAgg: Record<string, any>,
otherFilterBuilder: (
requestAgg: Record<string, any>,
key: string,
otherAgg: IBucketAggConfig
) => Filter
): estypes.SearchResponse<any> => {
const updatedResponse = cloneDeep(response);
each(otherResponse.aggregations['other-filter'].buckets, (bucket, key) => {
Expand All @@ -257,15 +271,8 @@ export const mergeOtherBucketAggResponse = (
otherAgg,
bucketKey
);
const requestFilterTerms = getOtherAggTerms(requestAgg, key, otherAgg);

const phraseFilter = buildPhrasesFilter(
otherAgg.params.field,
requestFilterTerms,
otherAgg.aggConfigs.indexPattern
);
phraseFilter.meta.negate = true;
bucket.filters = [phraseFilter];
const otherFilter = otherFilterBuilder(requestAgg, key, otherAgg);
bucket.filters = [otherFilter];
bucket.key = '__other__';

if (
Expand Down Expand Up @@ -294,3 +301,32 @@ export const updateMissingBucket = (
});
return updatedResponse;
};

export function constructSingleTermOtherFilter(
requestAgg: Record<string, any>,
key: string,
otherAgg: IBucketAggConfig
) {
const requestFilterTerms = getOtherAggTerms(requestAgg, key, otherAgg);

const phraseFilter = buildPhrasesFilter(
otherAgg.params.field,
requestFilterTerms,
otherAgg.aggConfigs.indexPattern
);
phraseFilter.meta.negate = true;
return phraseFilter;
}

export function constructMultiTermOtherFilter(
requestAgg: Record<string, any>,
key: string,
otherAgg: IBucketAggConfig
): Filter {
return {
query: requestAgg['other-filter'].filters.filters[key],
meta: {
negate: true,
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,43 @@
* Side Public License, v 1.
*/

import { buildPhrasesFilter, buildExistsFilter, buildPhraseFilter, Filter } from '@kbn/es-query';
import { buildPhraseFilter, Filter } from '@kbn/es-query';
import { IBucketAggConfig } from '../bucket_agg_type';
import { MultiFieldKey } from '../multi_field_key';

export const createFilterMultiTerms = (
aggConfig: IBucketAggConfig,
key: MultiFieldKey,
params: any
key: MultiFieldKey | string,
params: { terms: MultiFieldKey[] }
): Filter => {
const fields = aggConfig.params.fields;
const indexPattern = aggConfig.aggConfigs.indexPattern;

if (key.length === 1 && key[0] === '__other__') {
// TODO do this in a meaningful way
const terms = params.terms;
if (String(key) === '__other__') {
const multiTerms = params.terms;

const phraseFilter = buildPhrasesFilter(field, terms, indexPattern);
phraseFilter.meta.negate = true;
const perMultiTermQuery = multiTerms.map((multiTerm) =>
multiTerm.keys.map(
(partialKey, i) =>
buildPhraseFilter(indexPattern.getFieldByName(fields[i])!, partialKey, indexPattern).query
)
);

const filters: Filter[] = [phraseFilter];

if (terms.some((term: string) => term === '__missing__')) {
filters.push(buildExistsFilter(field, indexPattern));
}

return filters;
return {
meta: {
negate: true,
},
query: {
bool: {
should: perMultiTermQuery.map((multiTermQuery) => ({
bool: {
must: multiTermQuery,
},
})),
minimum_should_match: 1,
},
},
};
}
const partials = key.keys.map((partialKey, i) =>
buildPhraseFilter(indexPattern.getFieldByName(fields[i])!, partialKey, indexPattern)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ const id = Symbol('id');

export class MultiFieldKey {
[id]: string;
keys: string[];
keys: string[] | string;

constructor(bucket: any) {
this.keys = bucket.key;

this[id] = MultiFieldKey.idBucket(bucket);
}
static idBucket(bucket: any) {
return bucket.key.join(',,,,,');
return Array.isArray(bucket.key) ? bucket.key.join(',,,,,') : bucket.key;
}

toString() {
Expand Down
13 changes: 10 additions & 3 deletions src/plugins/data/common/search/aggs/buckets/multi_terms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
buildOtherBucketAgg,
mergeOtherBucketAggResponse,
updateMissingBucket,
constructMultiTermOtherFilter,
} from './_terms_other_bucket_helper';
import { MultiFieldKey } from './multi_field_key';

Expand Down Expand Up @@ -112,8 +113,7 @@ export const getMultiTermsBucketAgg = () => {
) => {
if (!resp.aggregations) return resp;
const nestedSearchSource = searchSource.createChild();
// TODO implement this
if (false && aggConfig.params.otherBucket) {
if (aggConfig.params.otherBucket) {
const filterAgg = buildOtherBucketAgg(aggConfigs, aggConfig, resp);
if (!filterAgg) return resp;

Expand All @@ -140,7 +140,14 @@ export const getMultiTermsBucketAgg = () => {
})
.toPromise();

resp = mergeOtherBucketAggResponse(aggConfigs, resp, response, aggConfig, filterAgg());
resp = mergeOtherBucketAggResponse(
aggConfigs,
resp,
response,
aggConfig,
filterAgg(),
constructMultiTermOtherFilter
);
}
if (aggConfig.params.missingBucket) {
resp = updateMissingBucket(resp, aggConfigs, aggConfig);
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/data/common/search/aggs/buckets/terms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
buildOtherBucketAgg,
mergeOtherBucketAggResponse,
updateMissingBucket,
constructSingleTermOtherFilter,
} from './_terms_other_bucket_helper';

export const termsAggFilter = [
Expand Down Expand Up @@ -120,7 +121,14 @@ export const getTermsBucketAgg = () =>
})
.toPromise();

resp = mergeOtherBucketAggResponse(aggConfigs, resp, response, aggConfig, filterAgg());
resp = mergeOtherBucketAggResponse(
aggConfigs,
resp,
response,
aggConfig,
filterAgg(),
constructSingleTermOtherFilter
);
}
if (aggConfig.params.missingBucket) {
resp = updateMissingBucket(resp, aggConfigs, aggConfig);
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta
static id = 'multi_terms';
static hidden = true;

convert = (val: string, type: FieldFormatsContentType) => {
convert = (val: unknown, type: FieldFormatsContentType) => {
const params = this._params;
const formats = params.paramsPerField.map((fieldParams) =>
getFieldFormat({ id: fieldParams.id, params: fieldParams })
);

if (val === '__other__') {
if (String(val) === '__other__') {
return params.otherBucketLabel;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ const getOtherBucketFilterTerms = (
return [
...new Set(
terms.filter((term) => {
const notOther = term !== '__other__';
const notMissing = term !== '__missing__';
const notOther = String(term) !== '__other__';
const notMissing = String(term) !== '__missing__';
return notOther && notMissing;
})
),
Expand Down Expand Up @@ -99,7 +99,10 @@ const createFilter = async (
if (value === null || value === undefined || !aggConfig.isFilterable()) {
return;
}
if (aggConfig.type.name === 'terms' && aggConfig.params.otherBucket) {
if (
(aggConfig.type.name === 'terms' || aggConfig.type.name === 'multi_terms') &&
aggConfig.params.otherBucket
) {
const terms = getOtherBucketFilterTerms(table, columnIndex, rowIndex);
filter = aggConfig.createFilter(value, { terms });
} else {
Expand Down

0 comments on commit 50df207

Please sign in to comment.