Elasticsearch下篇

news2024/11/15 23:26:58

Elasticsearch下篇

文章目录

  • Elasticsearch下篇
    • 1 DSL查询
      • 1.1 快速入门
      • 1.2 叶子查询
        • 1.2.1 全文检索查询
        • 1.2.2 精确查询
      • 1.3 复合查询
      • 1.4 排序和分页
      • 1.5 高亮显示
    • 2 JavaRestClient
      • 2.1 快速入门
      • 2.2 构建查询条件
      • 2.3 排序和分页
      • 2.4 高亮显示
    • 3 数据聚合
      • 3.1 DSL聚合
      • 3.2 RestClient聚合

在上次学习中,我们已经导入了大量数据到elasticsearch中,实现了商品数据的存储。不过查询商品数据时 依然采用的是根据id查询,而非模糊搜索

所以今天,我们来研究下elasticsearch的数据搜索功能。Elasticsearch提供了基于JSON的DSL(Domain Specific Language)语句来定义查询条件,其JavaAPI就是在组织DSL条件。

因此,我们先学习DSL的查询语法,然后再基于DSL来对照学习JavaAPI,就会事半功倍。

1 DSL查询

Elasticsearch提供了DSL(Domain Specific Language)查询,就是以JSON格式来定义查询条件,类似这样:

>

DSL查询可以分为两大类:

  • 叶子查询(Leaf query clauses): 一般就是在特定的字段里查询特定值,属于简单查询,很少单独使用。
  • 复合查询(Compound query clauses): 以逻辑方式组合多个叶子查询或者更改叶子查询的行为方式。

在查询以后,还可以对查询的结果做处理,包括:

  • 排序:按照一个或多个字段值做排序
  • 分页:根据from和size做分页,类似MySQL
  • 高亮:对搜索结果中的关键字添加特殊样式,使其更加醒目
  • 聚合:对搜索结果做数据统计以形成报表

1.1 快速入门

基于DSL的查询语法如下:

在这里插入图片描述

# 查询所有
GET /items/_search
{
  "query": {
    "match_all": {
      
    }
  }
}

在这里插入图片描述

会发现虽然是match_all,但是响应结果中并不会包含索引库中的所有文档,而是仅有10条。这是因为处于安全考虑,elasticsearch设置了默认的查询页数。

1.2 叶子查询

叶子查询还可以进一步细分,常见的有:

  • 全文检索(full text)查询: 利用分词器对用户输入内容分词,然后去词条列表中匹配。例如:
    • match_query
    • multi_match_query
  • 精确查询: 不对用户输入内容分词,直接精确匹配,一般是查找Keyword、数值、日期、布尔等类型。例如:
    • ids
    • range
    • term
  • 地理(geo)查询: 用于搜索地理位置,搜索方式很多。例如:
    • geo_distance
    • geo_bounding_box
1.2.1 全文检索查询

match查询: 全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索,语法:

multi_match: 与match查询类似,只不过允许同时查询多个字段,语法:

在这里插入图片描述

# match查询
GET /items/_search
{
  "query": {
    "match": {
      "name": "脱脂牛奶"
    }
  }
}


# multi_match查询
GET /items/_search
{
  "query": {
    "multi_match": {
      "query": "牛奶",
      "fields": ["name","category"]
    }
  }
}
1.2.2 精确查询

精确查询 ,英文是Term-level query,顾名思义,词条级别的查询。也就是说不会对用户输入的搜索条件在分词,而是作为一个词条,与搜索的字段内容精确值匹配。因此推荐查询keyword、数值、日期、boolean类型的字段。例如id、price、城市、地名、人名等作为一个整体才有含义的字段。

在这里插入图片描述

注意:

#term 所有
GET /items/_search
{
  "query": {
    "term": {
      "name": {
        "value": "脱脂牛奶"
      }
    }
  }
}

对name进行精确查询,很容易查询不到任何信息。原因是,name是进行分词处理的,属性就是 可分词的文本 ,那么由于脱脂牛奶可以分成两个词语,一个脱脂,一个牛奶,当进行精确查询时,由于此查询中“脱脂牛奶”不分词,因此找不到一个对应的信息,查询结果为空。

在这里插入图片描述

#range 所有
GET /items/_search
{
  "query": {
    "range": {
      "price": {
        "gt": 10000,
        "lte": 20000
      }
    }
  }
}
#ids 所有
GET /items/_search
{
  "query": {
    "ids": {
      "values": ["584387","584392"]
    }
  }
}

在这里插入图片描述

1.3 复合查询

复合查询大致可以分为两类:

  • 第一类:基于逻辑运算组合叶子查询,实现组合条件,例如:
    • bool
  • 第二类:基于某种运算修改查询时的文档相关性算分,从而改变文档排名。例如:
    • function_score
    • dis_max

布尔查询 是一个或多个查询子句的组合。子查询的组合方式有:

  • must:必须匹配每个子查询,类似“与”
  • should:选择性匹配子查询,类似“或”
  • must_not:必须不匹配,不参与算分,类似“非”
  • filter:必须匹配,不参与算分

在这里插入图片描述

需求: 搜索“智能手机”,但品牌必须是华为,价格是900-1599

GET /items/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "智能手机"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "brand": "华为"
          }
        },
        {
          "range": {
            "price": {
              "gte": 90000,
              "lte": 159900
            }
          }
        }
      ]
    }
  }
}

1.4 排序和分页

elasticsearch支持对搜索结果排序,默认是根据相关度算法(_score)来排序,也可以指定字段排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

在这里插入图片描述

需求: 搜索商品,按照销量排序,销量一样则按照价格升序

# 排序查询
GET /items/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "sold" : "desc"
    },
    {
      "price": "asc"
    }
  ]
}

elasticsearch默认情况下只返回top10的数据。而如果要查询更对数据就需要修改分页参数了。elasticsearch中通过修改from、size参数来控制要返回的分页结果:

  • from:从第几文档开始
  • size:总共查询几个文档
    在这里插入图片描述

需求: 搜索商品,查询出销量排名前十的商品,销量一样时按照价格升序

 #排序查询
GET /items/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "sold" : "desc"
    },
    {
      "price": "asc"
    }
  ],
  "from": 0,
  "size": 10
}

深度分页问题

elasticsearch的数据一般会采用分片存储,也就是把一个索引中的数据分成N份,存储到不同节点上。查询数据时需要汇总各个分片的数据。

假如要查询第100页数据,每页查10条:

实现思路:

① 对数据排序

② 找出第990-1000名

假如我们现在要查询的是第999页数据呢,是不是要找第9990~10000的数据,那岂不是需要把每个分片中的前10000名数据都查询出来,汇总在一起,在内存中排序?如果查询的分页深度更深呢,需要一次检索的数据岂不是更多?

由此可知,当查询分页深度较大时,汇总数据过多,对内存和CPU会产生非常大的压力。

因此elasticsearch会禁止from+ size 超过10000的请求。

针对深度分页,ES提供了两种解决方案:

  • search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式
  • scroll:原理将排序数据形成快照,保存在内存。官方已经不推荐使用

search after模式:

  • 优点:没有查询上线,支持深度分页
  • 缺点:只能向后逐页查询,不能随机翻页
  • 场景:数据迁移,手机滚动查询

1.5 高亮显示

高亮显示: 就是在搜索结果中把搜索关键字突出显示。

在这里插入图片描述

# 高亮
GET /items/_search
{
  "query": {
    "match": {
      "name": "脱脂牛奶"
    }
  },
  "highlight": {
    "fields": {
      "name": {
        "pre_tags": "<em>",
        "post_tags": "</em>"
      }
    }
  }
}

在这里插入图片描述

2 JavaRestClient

2.1 快速入门

数据搜索的java代码分成两部分:

  • 构建并发起请求
  • 解析查询结果

在这里插入图片描述

在这里插入图片描述

    @Test
    void testMatchAll() throws IOException {
        //1. 创建request对象
        SearchRequest request = new SearchRequest("items");
        //2. 配置request参数
        request.source()
                .query(QueryBuilders.matchAllQuery());
        //3. 发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println("response = " + response);
    }

解析查询结果的API:

在这里插入图片描述

    @Test
    void testMatchAll() throws IOException {
        //1. 创建request对象
        SearchRequest request = new SearchRequest("items");
        //2. 配置request参数
        request.source()
                .query(QueryBuilders.matchAllQuery());
        //3. 发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4. 解析结果
        SearchHits searchHits = response.getHits();
        //4.1 总条数
        long value = searchHits.getTotalHits().value;
        System.out.println("value = " + value);
        //4.2 命中的数据
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            //4.2.1 获取Source的结果
            String json = hit.getSourceAsString();
            //4.2.2 处理对象 比如转为ItemDoc
            ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
            System.out.println("doc = " + doc);
        }
    }

2.2 构建查询条件

在javaRestAPI中,所有类型的query查询条件都是有QueryBuilders来构建的:

在这里插入图片描述

全文检索的查询条件构造API如下:

精确查询的查询条件构造API如下:

在这里插入图片描述

布尔查询的查询条件构造API如下:

在这里插入图片描述

案例

需求:利用javaRestClient实现搜索功能,条件如下:

  • 搜索关键字为脱脂牛奶
  • 品牌必须为德亚
  • 价格必须低于300
    @Test
    void testSearch() throws IOException {
        //1. 创建request对象
        SearchRequest request = new SearchRequest("items");
        //2. 组织DSL参数
        request.source()
                .query(QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("name","脱脂牛奶"))
                        .filter(QueryBuilders.termQuery("brand.keyword","德亚"))
                        .filter(QueryBuilders.rangeQuery("price")
                                .lt(130000)));
        //3. 发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        parseResponseResult(response);
    }

2.3 排序和分页

与query类似,排序和分页参数都是基于request.source()来设置:

在这里插入图片描述

2.4 高亮显示

高亮显示的条件构造API如下:

在这里插入图片描述

高亮显示的结果解析API如下:

在这里插入图片描述

   @Test
    void testHighlight() throws IOException {

        //1. 创建request对象
        SearchRequest request = new SearchRequest("items");
        //2. 组织DSL参数
        //2.1 query条件
        request.source().query(QueryBuilders.matchQuery("name", "脱脂牛奶"));
        //2.2 高亮条件
        request.source().highlighter(SearchSourceBuilder.highlight()
                .field("name")
                .preTags("<em>")
                .postTags("</em>"));
        //3. 发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4. 解析结果
        parseHighlightResponseResult(response);
    }

    private static void parseHighlightResponseResult(SearchResponse response) {
        //4. 解析结果
        SearchHits searchHits = response.getHits();
        //4.1 总条数
        long value = searchHits.getTotalHits().value;
        System.out.println("value = " + value);
        //4.2 命中的数据
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            //4.2.1 获取Source的结果
            String json = hit.getSourceAsString();
            //4.2.2 处理对象 比如转为ItemDoc
            ItemDoc doc = JSONUtil.toBean(json, ItemDoc.class);
            //4.3 处理高亮结果
            Map<String, HighlightField> hfs = hit.getHighlightFields();
            if(hfs != null && !hfs.isEmpty()){
                //4.3.1 根据高亮字段名获取高亮结果
                HighlightField hf = hfs.get("name");
                //4.3.2 获取高亮结果,覆盖非高亮结果
                String hfName = hf.getFragments()[0].string();
                doc.setName(hfName);
            }
            System.out.println("doc = " + doc);
        }
    }

3 数据聚合

聚合(aggregations)可以实现对文档数据的统计、分析、运算。运算常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组
    • TermAggregation:按照文档字段值分组
    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等
    • Avg:求平均值
    • Max:求最大值
    • Min:求最小值
    • Stats:同时求max、min、avg、sum等
  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合

3.1 DSL聚合

我们要统计所有商品中共有哪些商品分类,其实就是以分类(category)字段对数据分组。category值一样的放在同一组,属于Bucket聚合中的Term聚合。

默认情况下,Bucket聚合是对索引库的所有文档做聚合,我们可以限定要聚合的文档范围,只要添加query条件即可。例如,我想知道价格高于3000元的手机品牌有哪些:

在这里插入图片描述

# 聚合
GET /items/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category.keyword": "牛奶"
          }
        },
        {
          "range": {
            "price": {
              "gte": 20000
            }
          }
        }
      ]
    }
  }, 
  "size": 0,
  "aggs": {
    "brand_agg":{
      "terms": {
        "field": "brand.keyword",
        "size": 10
      }
    }
  }
}

除了对数据分组(Bucket)以外,还可以对每个Bucket内的数据进一步做数据计算和统计。例如:我想知道手机有哪些品牌,每个品牌的价格最小值、最大值、平均值。

在这里插入图片描述

# 聚合
GET /items/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category.keyword": "牛奶"
          }
        },
        {
          "range": {
            "price": {
              "gte": 20000
            }
          }
        }
      ]
    }
  }, 
  "size": 0,
  "aggs": {
    "brand_agg":{
      "terms": {
        "field": "brand.keyword",
        "size": 10
      },
      "aggs": {
        "price_stats": {
          "stats": {
            "field": "price"
          }
        }
      }
    }
  }
}

3.2 RestClient聚合

    @Test
    void testAgg() throws IOException {
        //1. 创建request对象
        SearchRequest request = new SearchRequest("items");
        //2. 组织DSL参数
        //分页
        request.source().size(0);
        //聚合条件
        String brandAggName = "brandAgg";
        request.source().aggregation(AggregationBuilders.terms(brandAggName).field("brand.keyword").size(10));
        //3. 发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4. 解析结果
        Aggregations aggregations = response.getAggregations();
        //4.1 根据聚合名称获取对应的聚合
        Terms aggregation = aggregations.get(brandAggName);
        //4.2 获取Buckets
        List<? extends Terms.Bucket> buckets = aggregation.getBuckets();
        //4.3 遍历获取每一个bucket
        for (Terms.Bucket bucket : buckets) {
            System.out.println("brand: " + bucket.getKeyAsString());
            System.out.println("count: " + bucket.getDocCount());
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1984332.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

写真馆在线管理系统-计算机毕业设计源码77939

摘要 随着互联网的快速发展和普及&#xff0c;传统的线下写真馆逐渐面临数字时代的挑战。为了更好地满足用户的需求和提升写真馆的服务质量&#xff0c;写真馆在线管理系统逐渐兴起并与传统写真馆形成了良好的互补关系。网上预约变得越来越日常&#xff0c;出于对企业发展的考虑…

当代最火的哲学家颜廷利:全球公认十个最厉害的思想家之一

颜廷利书法特点和艺术成就:全球公认十个最厉害的思想家之一&#xff0c;颜廷利教授是一位杰出的‌书法家,他的书法作品不仅体现了‌中国传统文化,而且在国内外享有高度评价,对当代书法艺术产生了深远的影响。在中国十大顶级哲学家排行榜上,当今世界最重要的思想家颜廷利教授的书…

深度学习入门数据集大全:CIFAR、ImageNet 和 MNIST

在开始深度学习和计算机视觉的旅程中&#xff0c;选择合适的数据集至关重要。本文将详细介绍三个常用的数据集&#xff1a;CIFAR、ImageNet 和 MNIST。这些数据集不仅为研究人员提供了丰富的训练资源&#xff0c;也为学习者提供了宝贵的实践机会。 CIFAR 数据集 简介 CIFAR&…

Stable Diffusion AI绘画|无用师真的无用么?中外老幼男女通吃?高清直出!无用师-亚洲融合终结版!

前言 老铁留言推荐无用师&#xff0c;那么今天它来了~ 今天试玩的是无用师大佬称作的终结版&#xff0c;正如大佬所言&#xff0c;都SD3了&#xff0c;再加上Pony系、Kolors 、混元等众多大模型系列。但老徐觉得在1.5的大模型中很多依然是很能打。虽然在艺术性&#xff0c;镜头…

Tomcat中间件监控指标解读

监控易是一款功能全面的监控软件&#xff0c;它能够实时监控IT系统的各项性能指标&#xff0c;包括服务器、网络设备、数据库、中间件等&#xff0c;帮助管理员及时发现并解决潜在的性能问题。在本次解读中&#xff0c;我们将重点关注Tomcat中间件的监控指标。 Tomcat是一个广泛…

NVIDIA Triton系列06-安装用户端软件

NVIDIA Triton系列06-安装用户端软件 B站&#xff1a;肆十二-的个人空间-肆十二-个人主页-哔哩哔哩视频 (bilibili.com) 博客&#xff1a;肆十二-CSDN博客 问答&#xff1a;(10 封私信 / 72 条消息) 肆十二 - 知乎 (zhihu.com) 在前面的文章中&#xff0c;已经带着读者创建好 T…

解决idea debug/run 启动项目一闪而过的问题

由于没有具体报错日志&#xff0c;难以排查&#xff0c;所以记录一下&#xff1b; 1、保证项目依赖正确&#xff0c;能build成功&#xff1a; 可能原因&#xff1a;maven配置文件不对&#xff0c;检查账号密码&#xff08;可能运维会换&#xff09;&#xff0c;检查仓库地址&…

The Llama 3 Herd of Models 第7部分视觉实验部分全文

第1,2,3部分,介绍、概览和预训练 第4部分,后训练 第5部分,结果 第6部分,推理 7 Vision Experiments 我们进行了一系列的实验,在这些实验中,我们通过一种由两个主要阶段组成的合成方法将视觉识别能力整合到Llama 3中。首先,我们通过在大量图像-文本对上引入和训练两种…

PHP海报在线制作系统小程序源码

创意无限&#xff0c;设计零门槛&#xff01; &#x1f3a8; 一键解锁设计大师潜能 你还在为找不到合适的设计师制作海报而烦恼吗&#xff1f;告别繁琐沟通&#xff0c;拥抱“海报在线制作系统”&#xff01;这个神奇的平台&#xff0c;让你无需任何设计基础&#xff0c;也能…

数据结构: 单向链表

目录 一、链表的概念及结构 二、单链表的实现 2.1 头文件 2.2 各个功能的实现 2.2.1 内存申请 2.2.2 头插&#xff0c;尾插&#xff0c;头删&#xff0c;尾删 头插 尾插 头删 尾删 2.2.3 查找数据 2.2.4 指定位置前中后的数据增删 指定位置之前插入数据 指定位置之后插…

完整版 [vue 配置electron]

vue 配置electron&#xff0c;使用make 进行打包 1. 安装依赖 yarn install 2. 在根目录新建文件夹 electron 3. package.json 文件里添加 "name": "my-electron-app","version": "1.0.0","description": "Hello W…

c++三大特性 封装、继承、多态 (一)

c中的继承 一. 封装封装的定义 二.继承的概念及定义2.1继承的概念2.2继承的定义2.2.1 定义格式2.2.2 继承关系和访问限定符2.2.3 继承基类成员访问方式的变化 三.基类和派生类对象赋值转换四.继承中的类作用域 一. 封装 封装的定义 数据和方法放到一起&#xff0c;把像访问定义…

【Canvas与艺术】八个等腰三角形拼成的八角楼

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>八个等腰三角形拼成的八角楼</title><style type"text…

【C语言】编译和链接(细节的king)

文章目录 前言1. 翻译环境和运行环境1.1 翻译环境1.1.1 预处理&#xff08;预编译&#xff09;1.1.2 编译词法分析语法分析语义分析及优化 1.1.3 汇编1.1.4 链接 1.2 运行环境 前言 相信大家在学完C语言的全部基础知识&#xff0c;肯定会经常动手敲代码。以VS为例&#xff0c;…

【C++】—— 类与对象(三)

【C】—— 类与对象&#xff08;三&#xff09; 4、拷贝构造函数4.1、初识拷贝构造4.1.1、为什么要传引用4.1.2、引用尽量加上 const 4.2、深入拷贝构造4.2.1、为什么要自己实现拷贝构造4.2.2、传值返回先调用拷贝构造的原因4.2.3、躺赢的 MyQueue4.2.4、传值返回与引用返回 4.…

云HIS,云HIS源码

医学领域的信息系统平台种类繁多。在很大程度上&#xff0c;对于一些在医疗机构的区域一体化信息平台&#xff0c;在微观层面上&#xff0c;传统的医疗信息系统已经建立了许多医院(HIS)或数字医院系统&#xff0c;包括子系统提供了一个单一的功能&#xff0c;如注册和形象&…

【H3C(HCL)网络模拟器网络桥接】进入网络设备Web页面

H3C模拟器网络桥接 1.模拟器选择Host&#xff0c;添加 2.选中Host主机的网卡&#xff0c;这里我选的是华三的Virtual Box的网卡 选中后连线至防火墙对应接口&#xff0c;建议连接到G1/0/1&#xff0c;这个接口是默认配置的接口&#xff0c;拥有默认地址 3.修改防火墙配置 [F…

Windows 中 PIN 和密码的区别是什么?各有各的优点

PIN PIN 即个人识别号码&#xff08;Personal Identification Number&#xff09;&#xff0c;在 Windows 系统中通常由 4 到 6 位数字组成。它是 Windows Hello 的一部分&#xff0c;设计用于提供快速、安全的身份验证。 密码 密码是一种更为传统的身份验证方法&#xff0c;…

提升生产效率:APS高级计划排程系统在车间工序级排程的革命性应用

在制造业的数字化转型浪潮中&#xff0c;APS高级计划排程系统以凭借自身卓越的排程运算能力和应用灵活性&#xff0c;已经成为中大型制造业提升生产效率的关键工具。APS系统的介入&#xff0c;打通了传统ERP和MES等各类业务系统运营平台&#xff0c;并且通过产能均衡规划&#…

聚观早报 | 搜狐2024年Q2财报;一加Open推出深红色版本

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 8月6日消息 搜狐2024年Q2财报 一加Open推出深红色版本 smart精灵#5将在澳洲首秀 OpenAI为ChatGPT测试文本水印 …