-
Notifications
You must be signed in to change notification settings - Fork 8.3k
/
rollup_search_strategy.ts
104 lines (91 loc) · 2.98 KB
/
rollup_search_strategy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { HttpSetup } from 'src/core/public';
import {
SearchError,
getSearchErrorType,
IIndexPattern,
SearchStrategyProvider,
SearchResponse,
SearchRequest,
} from '../../../../../../src/plugins/data/public';
function serializeFetchParams(searchRequests: SearchRequest[]) {
return JSON.stringify(
searchRequests.map(searchRequestWithFetchParams => {
const indexPattern =
searchRequestWithFetchParams.index.title || searchRequestWithFetchParams.index;
const {
body: { size, aggs, query: _query },
} = searchRequestWithFetchParams;
const query = {
size,
aggregations: aggs,
query: _query,
};
return { index: indexPattern, query };
})
);
}
// Rollup search always returns 0 hits, but visualizations expect search responses
// to return hits > 0, otherwise they do not render. We fake the number of hits here
// by counting the number of aggregation buckets/values returned by rollup search.
function shimHitsInFetchResponse(response: SearchResponse[]) {
return response.map(result => {
const buckets = result.aggregations
? Object.keys(result.aggregations).reduce((allBuckets, agg) => {
return allBuckets.concat(
result.aggregations[agg].buckets || [result.aggregations[agg].value] || []
);
}, [])
: [];
return buckets && buckets.length
? {
...result,
hits: {
...result.hits,
total: buckets.length,
},
}
: result;
});
}
export const getRollupSearchStrategy = (fetch: HttpSetup['fetch']): SearchStrategyProvider => ({
id: 'rollup',
search: ({ searchRequests }) => {
// Serialize the fetch params into a format suitable for the body of an ES query.
const serializedFetchParams = serializeFetchParams(searchRequests);
const controller = new AbortController();
const promise = fetch('../api/rollup/search', {
signal: controller.signal,
method: 'POST',
body: serializedFetchParams,
});
return {
searching: promise.then(shimHitsInFetchResponse).catch(error => {
const {
body: { statusCode, error: title, message },
res: { url },
} = error;
// Format fetch error as a SearchError.
const searchError = new SearchError({
status: statusCode,
title,
message: `Rollup search error: ${message}`,
path: url,
type: getSearchErrorType({ message }) || '',
});
return Promise.reject(searchError);
}),
abort: () => controller.abort(),
};
},
isViable: (indexPattern: IIndexPattern) => {
if (!indexPattern) {
return false;
}
return indexPattern.type === 'rollup';
},
});