ElasticSearch: agregación de datos basada en DSL y JavaRestClient

Tabla de contenido

1. Agregación de datos

1.1 Conceptos básicos

1.1.1 Clasificación de agregación

1.1.2 Características

1.2 DSL implementa la agregación de depósitos

1.2.1 Sintaxis básica de agregación de depósitos

1.2.2 Clasificación de resultados de agregación de depósitos

1.2.3 Rango limitado de agregación de depósitos

1.3 DSL implementa la agregación de métricas

1.4 Implementar agregación basada en JavaRestClient

1.4.1 Solicitud de montaje

1.4.2 Respuesta del análisis

1.5. Caso del turismo oscuro

1.5.1 Demanda

1.5.2 Conexión a la interfaz frontal

1.5.3 Controlador de escritura

1.5.4 Agregar interfaz de filtros

1.5.5 Implementar interfaz


1. Agregación de datos


1.1 Conceptos básicos

1.1.1 Clasificación de agregación

Las agregaciones se utilizan para análisis estadísticos y operaciones con datos de documentos. Al igual que MySQL que aprendimos antes, también tiene funciones de agregación. Por ejemplo, puede usar avg para encontrar el promedio, max para encontrar el máximo, etc., y necesitan to be matched group by se usa para agrupar, y es también tiene funciones similares y es más rico.

Hay tres categorías principales de agregación en es:

1. Agregación de depósitos: se utiliza para agrupar documentos, similar al grupo por en MySQL, llamado "depósito", que es como clasificar basura y desempeña un papel en la clasificación y agrupación de diferentes documentos.

Hay dos tipos de agrupación de agregación de depósitos más utilizados:

TermAggregation: agrupar por valor de campo de documento (en realidad, este es el mismo efecto que agrupar por en mysql).

Histograma de datos: escalera de grupo por fecha, como un grupo por semana o un grupo por mes.

2. Agregación de métricas: calcule cada grupo de datos del documento, como valor máximo, valor mínimo, valor promedio, etc.

Esto es lo mismo que en mysql, como avg, max, min... 

Y también hay una agregación métrica especial en es: "estadísticas", que se puede utilizar para calcular el promedio, máximo, mínimo, etc. al mismo tiempo.

3. Agregación de canalización: se utiliza para agregar los resultados de otras agregaciones.

Por ejemplo, si agrupa datos de hoteles por marca, es decir, agregación de categorías, y luego calcula el precio promedio de hoteles de diferentes marcas, debe usar la agregación de métricas en este momento. Más adelante, si necesita calcular el precio promedio de diferentes marcas de hoteles, clasificando, luego los resultados de la medición deben agregarse nuevamente.

Ps: el método de agregación de canalizaciones rara vez se utiliza y no es el foco del aprendizaje posterior.

1.1.2 Características

No es difícil ver aquí que la agregación de la que acabamos de hablar agrupa cadenas por términos. En otras palabras, las palabras no se pueden segmentar en el futuro, y mucho menos fechas, valores y tipos booleanos.

Por lo tanto, los campos que participan en la agregación no deben estar segmentados por palabras.

1.2 DSL implementa la agregación de depósitos

1.2.1 Sintaxis básica de agregación de depósitos

La sintaxis de agregación de depósitos es la siguiente:

GET /索引库名/_search
{
  "size": 0,  // 设置size为0,结果中不包含文档,只包含聚合结果
  "aggs": { // 定义聚合
    "自定义聚合名": { //给聚合起个名字(自定义)
      "terms": { // 聚合的类型,按照品牌值聚合,所以选择 terms
        "field": "字段名", // 参与聚合的字段
        "size": 20 // 希望获取的聚合结果数量(值设置超过总数,也没有影响)
      }
    }
  }
}

Se puede ver que hay tres elementos de agregación: nombre de agregación, tipo de agregación y campo de agregación .

Por ejemplo, desea clasificar la información del hotel según la marca del hotel.

1.2.2 Clasificación de resultados de agregación de depósitos

De forma predeterminada, la agregación de depósitos cuenta la cantidad de documentos en el depósito, registrados como _count, y los clasifica en orden descendente de _count.

Por ejemplo, agrupe las marcas de hoteles y ordénelas en orden ascendente según el número de hoteles por marca:

1.2.3 Rango limitado de agregación de depósitos

De forma predeterminada, la agregación de Bucket agrega todos los documentos en la base de datos de índice. Aquí podemos limitar el alcance de los documentos que se agregarán, solo agregue condiciones de consulta.

Ps: la agregación de depósitos tiene una ventaja: si hay cientos de millones de datos en su biblioteca de índice, encontrar una agregación aún consumirá mucha memoria, por lo que al limitar el rango de búsqueda mediante consultas, puede reducir en gran medida el uso de memoria. .consumo.

Por ejemplo, busca hoteles con un precio menor o igual a 200 y clasifícalos por marca.

1.3 DSL implementa la agregación de métricas

La agregación de métricas consiste en calcular cada grupo por separado después de la agrupación (debe anidar aggs en aggs para realizar una subconsulta).

Por ejemplo, busque los valores mínimo, máximo, promedio y otros valores de la calificación del usuario (el campo es puntaje) de cada marca.

Aquí puedes usar la agregación de estadísticas.

Por supuesto, también puede ordenar en orden ascendente según la calificación promedio del usuario, de la siguiente manera

1.4 Implementar agregación basada en JavaRestClient

1.4.1 Solicitud de montaje

Ejemplo: Clasificar la información del hotel según la marca del hotel.

    @Test
    public void testAggregation() throws IOException {
        //1.准备 SearchRequest
        SearchRequest request = new SearchRequest("hotel");
        //2.准备参数
        request.source().size(0);
        request.source().aggregation(
                AggregationBuilders
                        .terms("brandAgg") //自定义聚合名
                        .field("brand") //根据 brand 的字段聚合
                        .size(10) //展示 10 组数据
        );
        //3.发送请求,接收响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析
        handlerResponse(response);
    }

Puedes compararlo con declaraciones DSL.

1.4.2 Respuesta del análisis

        //3.解析聚合查询
        Aggregations aggregations = response.getAggregations();
        Terms terms = aggregations.get("brandAgg");
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            System.out.println(key);
        }

Aquí puede comparar la sintaxis DSL para ver 

1.5. Caso del turismo oscuro

1.5.1 Demanda

La información de marca, ciudad y calificación de estrellas de la siguiente página de búsqueda no está codificada para esta página, sino que se obtiene agregando los datos del hotel en la base de datos del índice.

1.5.2 Conexión a la interfaz frontal

La página de inicio iniciará una solicitud al servidor para consultar los resultados de agregación de campos como marca, ciudad, calificación de estrellas, etc.

Los parámetros de solicitud aquí son exactamente los mismos que los RequestParam de la búsqueda anterior.

El formato de la respuesta devuelta aquí debe ser:

{"Ciudad": ["Shanghai", "Beijing"], "Marca": [....]...... }

Es la estructura de Map<String, List<String>>.

1.5.3 Controlador de escritura

Esto se utiliza para recibir solicitudes de front-end, el código es el siguiente.

    @RequestMapping("/filters")
    public Map<String, List<String>> filters(@RequestBody RequestParams params) {
        return hotelService.filters(params);
    }

1.5.4 Agregar interfaz de filtros

public interface IHotelService extends IService<Hotel> {

    PageResult search(RequestParams params);

    Map<String, List<String>> filters(RequestParams params);

}

1.5.5 Implementar interfaz

Al construir la solicitud de consulta aquí, primero pasa por un filtrado condicional (parámetros pasados ​​desde el front-end) y luego agrega la marca, la ciudad y la calificación de estrellas respectivamente.

Ps: aquí debe verificar la marca, la calificación de estrellas, la ciudad y si el tipo al crear la base de datos del índice es palabra clave, es decir, palabras inseparables, de lo contrario no se puede realizar la agregación.

    @Override
    public Map<String, List<String>> filters(RequestParams params) {
        try {
            //1.构造请求
            SearchRequest request = new SearchRequest("hotel");
            //2.准备参数
            // 1) 查询
            handlerBoolQueryBuilder(request, params);
            // 2) 设置 size
            request.source().size(0);
            // 3)聚合
            buildAggregation(request);
            //3.发送请求,接收响应
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //4.处理响应
            Map<String, List<String>> result = new HashMap<>();
            Aggregations aggregations = response.getAggregations();
            List<String> brandAgg = getAggListByName(aggregations, "brandAgg");
            result.put("brand", brandAgg);
            List<String> cityAgg = getAggListByName(aggregations, "cityAgg");
            result.put("city", cityAgg);
            List<String> starAgg = getAggListByName(aggregations, "starAgg");
            result.put("starName", starAgg);
            return result;
        } catch (IOException e) {
            System.out.println("[HotelService] 酒店数据聚合失败!");
            e.printStackTrace();
            return null;
        }
    }

    private List<String> getAggListByName(Aggregations aggregations, String aggName) {
        Terms terms = aggregations.get(aggName);
        List<? extends Terms.Bucket> buckets = terms.getBuckets();
        List<String> brandList = new ArrayList<>();
        for (Terms.Bucket bucket : buckets) {
            String key = bucket.getKeyAsString();
            brandList.add(key);
        }
        return brandList;
    }

    private void buildAggregation(SearchRequest request) {
        // 1) 聚合品牌
        request.source().aggregation(
                AggregationBuilders
                        .terms("brandAgg")
                        .field("brand")
                        .size(100)
        );
        // 2) 聚合城市
        request.source().aggregation(
                AggregationBuilders
                        .terms("cityAgg")
                        .field("city")
                        .size(100)
        );
        //3) 聚合星级
        request.source().aggregation(
                AggregationBuilders
                        .terms("starAgg")
                        .field("starName")
                        .size(100)
        );
    }

Supongo que te gusta

Origin blog.csdn.net/CYK_byte/article/details/133342870
Recomendado
Clasificación