SpringCloud(十)——ElasticSearch简单了解(二)DSL查询语句及RestClient查询文档

文章目录

  • 1. DSL查询文档
    • 1.1 DSL查询分类
    • 1.2 全文检索查询
    • 1.3 精确查询
    • 1.4 地理查询
    • 1.5 查询算分
    • 1.6 布尔查询
    • 1.7 结果排序
    • 1.8 分页查询
    • 1.9 高亮显示
  • 2. RestClient查询文档
    • 2.1 查询全部
    • 2.2 其他查询语句
    • 2.3 排序和分页
    • 2.4 高亮显示

1. DSL查询文档

1.1 DSL查询分类

  • 查询所有:查询出所有数据,一般测试用。例如:match_all
  • 全文检索查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:
    • match_query
    • multi_match_query
  • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:
    • ids
    • range
    • term
  • 地理查询:根据经纬度查询。例如:
    • geo_distance
    • geo_bounding_box
  • 复合查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:
    • bool
    • function_score

下面我们以一个基本的查询语句来举例,比如,我们需要查询索引库 hotel 全部内容,使用的DSL语句如下:

GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

1.2 全文检索查询

全文检索常用的有两个查询函数,分别是 match 以及 multi_match

  • match 函数会对用户输入内容分词,然后去倒排索引库检索,语法如下:
    GET /indexName/_search
    {
      "query": {
        "match": {
          "FIELD": "TEXT"
        }
      }
    }
    
    比如搜索 hotel 索引库中的 name 字段,如下:
    GET /hotel/_search
    {
      "query": {
        "match": {
          "name": "酒店"
        }
      }
    }
    
  • multi_match 函数与 match 类似,不过允许查询多个字段,语法如下:
    GET /indexName/_search
    {
      "query": {
        "multi_match": {
          "query": "TEXT",
          "fields": ["FIELD1", " FIELD2"]
        }
      }
    }
    
    比如搜索 hotel 索引库中的 name 字段,如下:
    GET /hotel/_search
    {
      "query": {
        "multi_match": {
          "query": "如家",
          "fields": ["name", " brand"]
        }
      }
    }
    

1.3 精确查询

精确查询的语句函数主要有 term 语句和 range 语句,精确查询必须要查询的内容与字段里面的所有内容完全匹配才行,一般的查询是keyword、数值、日期、boolean等类型字段。

  • term 的语法如下:
    GET /indexName/_search
    {
      "query": {
        "term": {
          "FIELD": {
            "value": "VALUE"
          }
        }
      }
    }
    
  • range 查询的语法如下:
    GET /indexName/_search
    {
      "query": {
        "range": {
          "FIELD": {
            "gte": 10,
            "lte": 20
          }
        }
      }
    }
    
    其中 gt 是大于,lt 是小于,gte 是大于等于,lte 是小于等于。

1.4 地理查询

地理查询主要是根据经纬度来进行查询的,主要使用的函数有 geo_bounding_boxgeo_distance

  • geo_bounding_box 函数的语法如下:
    GET /indexName/_search
    {
      "query": {
        "geo_bounding_box": {
          "FIELD": {
            "top_left": {
              "lat": 31.1,
              "lon": 121.5
            },
            "bottom_right": {
              "lat": 30.9,
              "lon": 121.7
            }
          }
        }
      }
    }
    
    该函数能够将在一个矩阵框中的经纬度全部筛选出来,该矩阵的左上角的点以及右下角的点如上述定义所示,根据这两个点已经就能够定义一个矩形了,。
  • geo_distance 函数的语法如下:
    GET /indexName/_search
    {
      "query": {
        "geo_distance": {
          "distance": "15km",
          "FIELD": "31.21,121.5"
        }
      }
    }
    
    该函数是筛选距离定义经纬度点指定距离内的所有点,这个距离指的是距定义点方圆的距离。

1.5 查询算分

在使用关键词等进行查询的时候,会有一个 _score 属性,这就是每条数据与查询关键词的相关性分数,该分数在ElasticSearch5.0之前是使用的 TF-IDF 算法进行的评分,ElasticSearch5.0之后是使用的 BM25 算法进行评分。
在这里插入图片描述
我们可以使用 function score query,修改文档的相关性算分(query score),根据新得到的算分排序。修改算分的示例语句如下:

GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": { "match": {"all": "外滩"} },
      "functions": [
        {
          "filter": {"term": {"id": "1"}},
          "weight": 10
        }
      ],
      "boost_mode": "multiply"
    }
  }
}

在上面的例句中,

  • query 是正常的查询语句
  • filter 表示过滤条件,符合条件的文档才会被重新算分
  • weight 是指算分函数,算分函数的结果称为 function score ,将来会与原始的 query score 运算,得到新算分,常见的算分函数有:
    • weight:给一个常量值,作为函数结果(function score)
    • field_value_factor:用文档中的某个字段值作为函数结果
    • random_score:随机生成一个值,作为函数结果
    • script_score:自定义计算公式,公式结果作为函数结果
  • boost_mode 定义function score与query score的运算方式,常见的加权方式如下:
    • multiply:两者相乘。默认就是这个
    • replace:用function score 替换 query score
    • 其它:sum、avg、max、min

1.6 布尔查询

布尔查询时一个或多个查询的字句,子查询的组合方式有:

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

示例如下:

GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {"term": {"city": "上海" }}
      ],
      "should": [
        {"term": {"brand": "皇冠假日" }},
        {"term": {"brand": "华美达" }}
      ],
      "must_not": [
        { "range": { "price": { "lte": 500 } }}
      ],
      "filter": [
        { "range": {"score": { "gte": 45 } }}
      ]
    }
  }
}

1.7 结果排序

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

GET /indexName/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "FIELD": "desc"  // 排序字段和排序方式ASC、DESC
    }
  ]
}

以上就是指定字段的排序, ASC 代表升序,DASC 代表降序,如果有多个排序字段,那么按照从上到下的优先级进行排序。

举个例子,如果我们想要按照某一个经纬度的距离进行排序,那么模板如下:

GET /indexName/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance" : {
          "FIELD" : "纬度,经度",
          "order" : "asc",
          "unit" : "km"
      }
    }
  ]
}

1.8 分页查询

ElasticSearch查询时默认只显示10条数据,那如果我们想要看到其他的数据怎么办呢?这就涉及到了分页。ElasticSearch分页的方式有很多种,这里讲一下使用 from, size 参数以及 search after 来进行分页。

  • 使用 from, size 两个参数进行分页。可以在搜索时规定这两个参数的值, from 表示从何处开始进行查看,默认是 0 0 0size 表示每次查询的信息有多少条。比如每也10条数据,我们想要查看第二页的数据,那么就需要设置 from: 10,size:10 ,格式如下:

    GET /hotel/_search
    {
     "query": {
       "match_all": {}
     },
     "from": 990, // 分页开始的位置,默认为0
     "size": 10, // 期望获取的文档总数
     "sort": [
       {"price": "asc"}
     ]
    }
    

    但是,这种方式要求 from+size 不大于 10000 10000 10000 ,且该方式是先查询所有的数据,然后再对数据进行截取,不可避免的,该方式会面临深度分页问题,即我们的ElasticSearch肯定是要有集群的,当我们需要取出前 1000 1000 1000 个结果时,需要整理每个集群中的结果,再重新排序,再选出前 1000 1000 1000 个,但是,如果结果集很大,这对内存以及CPU的消耗就很大。

  • 使用 search after 进行分页。针对深度分页,ElasticSearch提供了 search after 方法,该方法没有查询上限,只限制了单次的 size 不超过 10000 10000 10000search after 方法分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。

    例如,我们查询到了第一页的数据,最后一条数据如下:
    在这里插入图片描述
    我们将最后一条数据的 sort 字段复制到 search_after 中,再规定一个 size 属性,就能够在该条数据之后再显示 size 条数据,语法模板如下:

    GET /hotel/_search
    {
     "query": {
       "match_all": {}
     },
     "search_after": [
        161
      ],
     "size": 10,
     "sort": [
       {"price": "asc"}
     ]
    }
    

1.9 高亮显示

在使用搜索引擎进行搜索时,我们发现我们输入的关键词显示都是用了高亮进行显示,这就是搜索结果的高亮。其实,这种高亮的显示是在搜索结果中将关键字用标签进行标注出来,再到页面中进行CSS的渲染。默认在进行高亮查询时会在高亮字段前后添加 em 标签,如果想添加其他标签可以进行更改,语法模板如下:

GET /hotel/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  },
  "highlight": {
    "fields": { // 指定要高亮的字段,可以添加多个字段
      "FIELD": {
        "pre_tags": "<em>",  // 用来标记高亮字段的前置标签,默认就是em标签,所以可以不写
        "post_tags": "</em>" // 用来标记高亮字段的后置标签
      }
    }
  }
}

这里我们对酒店数据进行查询的例子如下:

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  },
  "highlight": {
    "fields": { 
      "name": {
        "require_field_match": "false"
      }
    }
  }
}

在上面的搜索中, all 字段是 name, brand 等字段 copy_to 后的属性,而下面高亮显示的属性是 name 属性,这就导致了查询的属性与高亮显示的属性不一致的情况,这种情况默认是不会进行高亮显示的,需要查询的属性与高亮显示的属性一致才进行高亮显示。但是我们就可以设置 require_field_match 属性为 false 控制高亮显示与查询字段和高亮显示的字段无关。

高亮结果显示如下:
在这里插入图片描述

2. RestClient查询文档

2.1 查询全部

查询全部的代码如下所示,

    @Test
    void testMatchAll() throws IOException {
        //1.准备Request对象
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        //3.发送请求
        SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        //4.解析响应
        SearchHits searchHits = response.getHits();
        //5.1 获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共有" + total + "条数据");
        //5.2 文档数组存储文档
        SearchHit[] hits = searchHits.getHits();
        for(SearchHit hit: hits){
            //6.获取文档source
            String json = hit.getSourceAsString();
            //7.反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println(hotelDoc);
        }
        System.out.println(response);

    }

其中每一段代码与DSL语句的对应关系如下:
在这里插入图片描述

2.2 其他查询语句

其实其他查询语句与上述查询全部的语句中大部分代码是类似的,唯一变化的是 request.source().query()query 的参数。

  • match
    // 分别是字段名和查询的语句
    request.source().query(QueryBuilders.matchQuery("all", "如家"));
    
  • multi_match
    // 分别是查询词以及查询字段
    request.source().query(QueryBuilders.matchQuery("如家", "name", "brand"));
    
  • term
    // 分别是查询字段以及查询词
    request.source().query(QueryBuilders.termQuery("city", "成都"));
    
  • range
    // 分别是查询词以及查询条件
    request.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(300));
    
  • 布尔查询
    // 构建布尔查询
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    // must语句
    boolQuery.must(QueryBuilders.termQuery("city", "成都"));
    //filter语句
    boolQuery.filter(QueryBuilders.rangeQuery("price").gte(100).lte(300))
    request.source().query(boolQuery);
    

2.3 排序和分页

排序与分页的代码也仅需要在 request.source().query() 上进行修改即可,修改示例如下:

request.source().query(QueryBuilders.termQuery("city", "成都"));
// 排序
request.source().sort("price", SortOrder.ASC);
//分页
request.source().from(0).size(10);

2.4 高亮显示

高亮显示仅需要在查询的内容后面添加一行代码即可,如下:

// 设置高亮显示并关闭查询字段与高亮字段一致
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));

但是,设置了高亮后输出发现并不是高亮的内容,需要高亮的内容前后没有标签,这是怎么回事呢?

回顾上面可以发现,高亮的内容与 _source 内容是分开的,是重新的一个字段,于是,我们需要用高亮的字段覆盖原来的字段,那么循环里面的代码如下:

for(SearchHit hit: hits){
    //6.获取文档source
    String json = hit.getSourceAsString();
    //7.反序列化
    HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
    //获取高亮结果
    Map<String, HighlightField> highlightFieldMap = hit.getHighlightFields();
    //简洁判断,判断highlightFieldMap是否为空或者size==0
    if(!CollectionUtils.isEmpty(highlightFieldMap)){
        //获取highlight属性中的name属性
        HighlightField highlightField = highlightFieldMap.get("name");
        if(highlightField != null){
            //得到name属性的第一个值的字符串
            String name = highlightField.getFragments()[0].string();
            //覆盖原本的值
            hotelDoc.setName(name);
        }
    }
    System.out.println(hotelDoc);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【图像分割】实现snake模型的活动轮廓模型以进行图像分割研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

机器人中的数值优化(七)——修正阻尼牛顿法

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

Ubuntu入门03——Ubuntu用户操作

1.Ubuntu如何进入root用户 进入ROOT用户的指令&#xff1a; Linux用su命令来切换用户&#xff1a; su root执行命令后&#xff0c;会提示你输入密码&#xff0c;而Ubuntu是没有设置root初始密码的。 若su命令不能切换root&#xff0c;提示su: Authentication failure&#x…

ASP.NET修改默认端口

找到发布目录下的appsettings.json文件 加入下面内容 "Kestrel":{"Endpoints": {"Https": {"Url": "https://*:8827"},"Http": {"Url": "http://*:8828"}}} 不使用https的话去掉https,修改…

二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO

简介 pwn是ctf比赛的方向之一&#xff0c;也是门槛最高的&#xff0c;学pwn前需要很多知识&#xff0c;这里建议先去在某宝上买一本汇编语言第四版&#xff0c;看完之后学一下python和c语言&#xff0c;python推荐看油管FreeCodeCamp的教程&#xff0c;c语言也是 pwn题目大部…

【洛谷】P3853 路标设置

原题链接&#xff1a;https://www.luogu.com.cn/problem/P3853 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 整体思路&#xff1a;二分答案 由题意知&#xff0c;公路上相邻路标的最大距离定义为该公路的“空旷指数”。在公路上增设一些路标&…

【ELK日志收集系统】

目录 一、概述 1.作用 2.为什么使用&#xff1f; 二、组件 1.elasticsearch 1.1 作用 1.2 特点 2.logstash 2.1 作用 2.2 工作过程 2.3 INPUT 2.4 FILETER 2.5 OUTPUTS 3.kibana 三、架构类型 1.ELK 2.ELKK 3.ELFK 4.ELFKK 四、案例 - 构建ELK集群 1.环境…

MFC网络编程简单例程

目录 一、关于网络的部分概念1 URL(网址)及URL的解析2 URL的解析3 域名及域名解析3 IP及子网掩码4 什么是Web服务器5 HTTP的基本概念6 Socket库概念7 协议栈8 Socket库收发数据基本步骤 二、基于TCP的网络应用程序三、基于UDP的网络应用程序 一、关于网络的部分概念 1 URL(网址…

git在windows上安装

介绍git工具在windows上如何安装 git官网下载地址 1.1、下载 https://github.com/git-for-windows/git/releases/download/v2.36.0.windows.1/Git-2.36.0-64-bit.exe自行选择版本&#xff0c;这里我选择的是 Git-2.36.0-64-bit这个版本 1.2、安装 安装路径选择英文且不带空格…

【计算机网络】HTTP

文章目录 1.HTTP概念2. URLurlencode 和 urldecode转义规则 3. HTTP的宏观理解HTTP的请求HTTP的响应 4. 见一见HTTP请求和响应请求报头 1. 模拟一个简单的响应response响应报头 2. 从路径中获取内容ReadFile函数的实现 3.不同资源进行区分反序列化的实现ReadOneLine函数的实现P…

docker-compose 部署nacos 整合 postgresql 为DB

标题docker-compose 部署nacos 整合 postgresql 为DB 前提&#xff1a; 已经安装好postgresql数据库 先创建好一个数据库 nacos&#xff0c;执行以下sql: /** Copyright 1999-2018 Alibaba Group Holding Ltd.** Licensed under the Apache License, Version 2.0 (the "…

Java:Springboot和React中枚举值(数据字典)的使用

目录 1、开发中的需求2、实现效果3、后端代码4、前端代码5、接口数据6、完整代码7、参考文章 1、开发中的需求 开发和使用过程中&#xff0c;通常会涉及四个角色&#xff1a;数据库管理员、后端开发人员、前端开发人员、浏览者 数据库使用int类型的数值进行存储&#xff08;e…

POSTGRESQL WAL 日志问题合集之WAL 如何解析

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请加 liuaustin3微信号 &#xff0c;在新加的朋友会分到3群 &#xf…

最小二乘法处理线性回归

最小二乘法是一种数学优化技术&#xff0c;用于查找最适合一组数据点的函数。 该方法主要用于线性回归分析&#xff0c;当然&#xff0c;也可用于非线性问题。 开始之前&#xff0c;我们先理解一下什么是回归。 回归&#xff1a;回归是一种监督学习算法&#xff0c;用于建模和…

MySql时间

一、查询 查询mysql当前时间 SELECT now();查询mysql时区 show variables like%time_zone;二、修改时区 set global time_zone 8:00; &#xff08;修改mysql全局时区为北京时间&#xff0c;也就是我们所在的东8区&#xff0c;需要root权限&#xff09; set time_zone 8:0…

销量蹭蹭上涨!亚马逊上这几款宿舍神器火爆了!

一、BedShelfie床边置物架 每年返校季&#xff0c;收纳工具都是最畅销的产品。在亚马逊床头柜热销榜单中&#xff0c;这款产品位居第二。过去一个月里&#xff0c;有1000多名用户购买了这件产品。 二、U Brands磁性干擦日历板 目前&#xff0c;亚马逊上这款产品已经卖到断货。…

自建音乐服务器Navidrome之一

这里写自定义目录标题 1.1 官方网站 2. Navidrome 简介2.1 简介2.2 特性 3. 准备工作4. 视频教程5. 界面演示5.1 初始化页5.2 专辑页 前言 之前给大家介绍过 Koel 音频流服务&#xff0c;就是为了解决大家的这个问题&#xff1a;下载下来的音乐&#xff0c;只能在本机欣赏&…

The remote endpoint was in state [TEXT_FULL_WRITING]

报这个错是因为在websocket接收与发送消息时&#xff0c;资源互抢造成的&#xff0c;有很多帖子说将session锁住&#xff0c; 但是同一个账号多个客户端登陆的时候&#xff0c;session是不同的&#xff0c;所以只能锁住一个session&#xff0c;还是出现这个问题。 解决办法&a…

Go 官方标准编译器中所做的优化

本文是对#102 Go 官方标准编译器中实现的优化集锦汇总[1] 内容的记录与总结. 优化1-4: 字符串和字节切片之间的转化 1.紧跟range关键字的 从字符串到字节切片的转换&#xff1b; package mainimport ( "fmt" "strings" "testing")var cs10086 s…

正则表达式练习

(function() {//#region 定义正则表达式// const reg /前端/g;// ------------test-------------// const res reg.test("学java,找黑马");// console.log(res)// ------------exec--------------// const res reg.exec("学好前端&#xff0c;找黑马"…