Skip to content

Commit

Permalink
Phase 1 of search services
Browse files Browse the repository at this point in the history
  • Loading branch information
stacey-gammon committed Sep 30, 2019
1 parent 3a7d9fa commit ddfed3f
Show file tree
Hide file tree
Showing 60 changed files with 3,043 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/plugins/search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# search

The `search` plugin provides the ability to register search strategies that take in a request
object, and return a response object, of a given shape.

Both client side search strategies can be registered, as well as server side search strategies.

The `search` plugin includes two one concrete client side implementations -
`SYNC_SEARCH_STRATEGY` and `ES_SEARCH_STRATEGY` which uses `SYNC_SEARCH_STRATEGY`. There is also one
default server side search strategy, `ES_SEARCH_STRATEGY`.

Includes the `esSearch` plugin in order to search for data from Elasticsearch using Elasticsearch
DSL.
172 changes: 172 additions & 0 deletions src/plugins/search/common/es_search/elasticsearch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { SearchResponse, SearchParams } from 'elasticsearch';

export interface StringMap<T = unknown> {
[key: string]: T;
}

export type IndexAsString<Map> = {
[k: string]: Map[keyof Map];
} & Map;

export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

export interface BoolQuery {
must_not: Array<Record<string, any>>;
should: Array<Record<string, any>>;
filter: Array<Record<string, any>>;
}

// extending SearchResponse to be able to have typed aggregations

type AggregationType =
| 'date_histogram'
| 'histogram'
| 'terms'
| 'avg'
| 'top_hits'
| 'max'
| 'min'
| 'percentiles'
| 'sum'
| 'extended_stats'
| 'filter'
| 'filters'
| 'cardinality'
| 'sampler'
| 'value_count';

type AggOptions = AggregationOptionMap & {
[key: string]: any;
};

// eslint-disable-next-line @typescript-eslint/prefer-interface
export type AggregationOptionMap = {
aggs?: {
[aggregationName: string]: {
[T in AggregationType]?: AggOptions & AggregationOptionMap;
};
};
};

type SubAggregation<T> = T extends { aggs: any } ? AggregationResultMap<T['aggs']> : {};

// eslint-disable-next-line @typescript-eslint/prefer-interface
type BucketAggregation<SubAggregationMap, KeyType = string> = {
buckets: Array<
{
key: KeyType;
key_as_string: string;
doc_count: number;
} & (SubAggregation<SubAggregationMap>)
>;
};

type FilterAggregation<SubAggregationMap> = {
doc_count: number;
} & SubAggregation<SubAggregationMap>;

// eslint-disable-next-line @typescript-eslint/prefer-interface
type FiltersAggregation<SubAggregationMap> = {
buckets: Array<
{
doc_count: number;
} & SubAggregation<SubAggregationMap>
>;
};

type SamplerAggregation<SubAggregationMap> = SubAggregation<SubAggregationMap> & {
doc_count: number;
};

interface AggregatedValue {
value: number | null;
}

type AggregationResultMap<AggregationOption> = IndexAsString<
{
[AggregationName in keyof AggregationOption]: {
avg: AggregatedValue;
max: AggregatedValue;
min: AggregatedValue;
sum: AggregatedValue;
value_count: AggregatedValue;
// Elasticsearch might return terms with numbers, but this is a more limited type
terms: BucketAggregation<AggregationOption[AggregationName], string>;
date_histogram: BucketAggregation<AggregationOption[AggregationName], number>;
histogram: BucketAggregation<AggregationOption[AggregationName], number>;
top_hits: {
hits: {
total: number;
max_score: number | null;
hits: Array<{
_source: AggregationOption[AggregationName] extends {
Mapping: any;
}
? AggregationOption[AggregationName]['Mapping']
: never;
}>;
};
};
percentiles: {
values: {
[key: string]: number;
};
};
extended_stats: {
count: number;
min: number | null;
max: number | null;
avg: number | null;
sum: number;
sum_of_squares: number | null;
variance: number | null;
std_deviation: number | null;
std_deviation_bounds: {
upper: number | null;
lower: number | null;
};
};
filter: FilterAggregation<AggregationOption[AggregationName]>;
filters: FiltersAggregation<AggregationOption[AggregationName]>;
cardinality: {
value: number;
};
sampler: SamplerAggregation<AggregationOption[AggregationName]>;
}[AggregationType & keyof AggregationOption[AggregationName]];
}
>;

export type IEsRawSearchResponse<THitType, TSearchParams extends SearchParams> = Pick<
SearchResponse<THitType>,
Exclude<keyof SearchResponse<THitType>, 'aggregations'>
> &
(TSearchParams extends { body: Required<AggregationOptionMap> }
? {
aggregations?: AggregationResultMap<TSearchParams['body']['aggs']>;
}
: {});

export interface ESFilter {
[key: string]: {
[key: string]: string | string[] | number | StringMap | ESFilter[];
};
}
20 changes: 20 additions & 0 deletions src/plugins/search/common/es_search/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from './types';
31 changes: 31 additions & 0 deletions src/plugins/search/common/es_search/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { SearchParams } from 'elasticsearch';
import { IEsRawSearchResponse } from './elasticsearch';
import { IKibanaSearchRequest, IKibanaSearchResponse } from '../types';

export const ES_SEARCH_STRATEGY = 'es';

export interface IEsSearchRequest extends IKibanaSearchRequest {
params: SearchParams;
}

export interface IEsSearchResponse<Hits, TSearchParams> extends IKibanaSearchResponse {
rawResponse: IEsRawSearchResponse<Hits, TSearchParams>;
}
26 changes: 26 additions & 0 deletions src/plugins/search/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { ES_SEARCH_STRATEGY } from './es_search';

export { IKibanaSearchResponse, IKibanaSearchRequest } from './types';

export const DEFAULT_SEARCH_STRATEGY = ES_SEARCH_STRATEGY;

export { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from './es_search';
55 changes: 55 additions & 0 deletions src/plugins/search/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export interface IKibanaSearchResponse {
/**
* Some responses may contain a unique id to identify the request this response came from.
*/
id?: string;

/**
* If hasProgressInformation, this should be implemented and return progress
* information.
*/
getPercentComplete?: () => number;

/**
* If relevant to the search strategy, return a total number
* that represents how progress is indicated.
*/
total?: number;

/**
* If relevant to the search strategy, return a total number
* that represents how progress is indicated.
*/
loaded?: number;
}

export interface IKibanaSearchRequest {
/**
* An id can be used to uniquely identify this request.
*/
id?: string;

/**
* Optionally tell search strategies to output debug information.
*/
debug?: boolean;
}
6 changes: 6 additions & 0 deletions src/plugins/search/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "search",
"version": "kibana",
"server": true,
"ui": true
}
20 changes: 20 additions & 0 deletions src/plugins/search/public/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export const SYNC_SEARCH_STRATEGY = 'SYNC_SEARCH_STRATEGY';
Loading

0 comments on commit ddfed3f

Please sign in to comment.