Elasticsearch(十一)搜索---搜索匹配功能②--range查询和exists查询

这篇具有很好参考价值的文章主要介绍了Elasticsearch(十一)搜索---搜索匹配功能②--range查询和exists查询。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、前言

继上一节学习了ES的搜索的查询全部和term搜索后,此节将把搜索匹配功能剩余的2个学习完,分别是range搜索和exists搜索

二、range范围搜索

range查询用于范围查询,一般是对数值型和日期型数据的查询。使用range进行范围查询时,用户可以按照需求中是否包含边界数值进行选项设置,可供组合的选项如下:

  • gt:大于;
  • lt 小于;
  • gte 大于等于;
  • lte 小于等于;

其请求形式如下:

GET /hotel/_search
{
 
 "query": {
   "range": {
     "FIELD": {   //需要范围查询的列
       "gte": "${VALUE1}",   //大于等于value1
       "lte": "${VALUE2}"    //小于等于value2
     }
   }
 }
}

以下是数值类型的查询示例,查询住宿价格在500~600(包含边界值)元的酒店:

GET /hotel/_search
{
 
 "query": {
   "range": {
     "price": {
       "gte": "500",
       "lte": "600"
     }
   }
 }
}

ES返回的数据如下:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "hotel",
        "_type" : "_doc",
        "_id" : "001",
        "_score" : 1.0,
        "_source" : {
          "title" : "文雅酒店",
          "city" : "北京",
          "price" : "558.00",
          "create_time" : "2020-03-29 21:00:00",
          "amenities" : "浴池,普通停车场/充电停车场",
          "full_room" : true,
          "location" : {
            "lat" : 36.940243,
            "lon" : 120.394
          },
          "praise" : 10
        }
      },
      {
        "_index" : "hotel",
        "_type" : "_doc",
        "_id" : "006",
        "_score" : 1.0,
        "_source" : {
          "title" : "京盛集团精选酒店",
          "city" : "上海",
          "price" : "500.00",
          "create_time" : "2022-01-29 22:50:00",
          "full_room" : true,
          "location" : {
            "lat" : 40.918229,
            "lon" : 118.422011
          },
          "praise" : 20
        }
      }
    ]
  }
}

如果我需要查询大于500元(不包含边界值)的酒店:

GET /hotel/_search
{
 
 "query": {
   "range": {
     "price": {
       "gt": "500"
     }
   }
 }
}

注意,使用range查询时,查询值必须符合该字段在mappings中设置的规范。例如,在酒店索引中,price字段是double类型,则range应该使用数值型或者数值类型的字符串形式,不能使用其他形式。以下示例将导致ES返回错误:

GET /hotel/_search
{
 
 "query": {
   "range": {
     "price": {
       "gt": "abc"
     }
   }
 }
}

执行上述DSL后,ES返回信息如下:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "query_shard_exception",
        "reason" : "failed to create query: For input string: \"abc\"",
        "index_uuid" : "az-MqIf9QM6asEIfivIBLQ",
        "index" : "hotel"
      }
    ],
    "type" : "search_phase_execution_exception",   //range查询解析异常
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "hotel",
        "node" : "ER773I31Sx-wJuJwJCh7Ng",
        "reason" : {
          "type" : "query_shard_exception",
          //构建range查询时出现异常
          "reason" : "failed to create query: For input string: \"abc\"",
          "index_uuid" : "az-MqIf9QM6asEIfivIBLQ",
          "index" : "hotel",
          "caused_by" : {
          //字符串类型不能转换为range查询对应的数值型数据
            "type" : "number_format_exception",
            "reason" : "For input string: \"abc\""
          }
        }
      }
    ]
  },
  "status" : 400
}

和term查询类似,查询日期型的字段时,需要遵循该字段在mappings中定义的格式进行查询。例如create_time使用的格式为"yyyy-MM-dd HH:mm:ss",则range查询应该使用如下方式:

GET /hotel/_search
{
 
 "query": {
   "range": {
     "create_time": {
       "gte": "2021-02-27 22:00:00",
       "lte": "2024-02-27 22:00:00"
     }
   }
 }
}

在Java客户端上构建range请求是使用QueryBuilders.rangeQuery()方法实现的,该方法的参数为字段名称,然后再调用对应的方法即可构建相应的查询范围。可以调用gt()、lt()、gte()、lte()等方法分别实现大于、小于、大于等于、小于等于等查询范围。在使用时支持链式编程,可以连着使用"."操作符,这样不用拆分语句,也比较容易理解,一下通过range查询完成一个createTime大于等于输入的createTimeStart和小于等于createEnd的一个范围查询
Service层:

		public List<Hotel> rangeQuery(HotelDocRequest hotelDocRequest) throws IOException {
		//新建搜索请求
		String indexName = hotelDocRequest.getIndexName();
		if (CharSequenceUtil.isBlank(indexName)) {
			throw new SearchException("索引名不能为空");
		}
		SearchRequest searchRequest = new SearchRequest(indexName);
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		Date createTimeStart = hotelDocRequest.getCreateTimeStart();
		String createTimeStartToSearch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTimeStart);
		Date createTimeEnd = hotelDocRequest.getCreateTimeEnd();
		String createTimeEndToSearch = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(createTimeEnd);
		searchSourceBuilder.query(QueryBuilders.rangeQuery("create_time").gte(createTimeStartToSearch).lte(createTimeEndToSearch));
		searchRequest.source(searchSourceBuilder);
		return getQueryResult(searchRequest);
	}

Controller层:

	@PostMapping("/query/range")
	public FoundationResponse<List<Hotel>> rangeQuery(@RequestBody HotelDocRequest hotelDocRequest) {
		try {
			List<Hotel> hotelList = esQueryService.rangeQuery(hotelDocRequest);
			if (CollUtil.isNotEmpty(hotelList)) {
				return FoundationResponse.success(hotelList);
			} else {
				return FoundationResponse.error(100,"no data");
			}
		} catch (IOException e) {
			log.warn("搜索发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		} catch (Exception e) {
			log.error("服务发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		}
	}

postman调用该接口:
Elasticsearch(十一)搜索---搜索匹配功能②--range查询和exists查询

三、exists查询

在某些场景下,我们希望找到某个字段不为空的文档,则可以用exists搜索。字段不为空的条件有:

  • 值存在且不是null
  • 值不是空数组
  • 值是数组,但不是[null]

为方便测试,给索引hotel增加tag字段,DSL如下:

POST /hotel/_mapping
{
    "properties": {
      "tag":{
        "type": "keyword"
      }
    }
}

下面向该索引中分别写入3条字段为空的数据。
添加tag字段值为null的文档,DSL如下:

POST /hotel/_create/020
{
  "title":"环球酒店",
  "tag":null
}

添加tag字段是空数组的文档,DSL如下:

POST /hotel/_create/021
{
  "title":"环球酒店2",
  "tag":[]
}

添加tag为数组,其中只有一个元素,且该元素为null的文档,DSL如下:

POST /hotel/_create/022
{
  "title":"环球酒店3",
  "tag":[null]
}

上面3种情况的数据使用exists查询都不命中,查询的DSL如下:

GET /hotel/_search
{
  "query": {
    "exists": {
      "field": "tag"
    }
  }
}

返回结果如下:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,          //命中的文档个数为0
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]   //命中的文档集合为空
  }
}

在java客户端中进行查询时,可以调用QueryBuilders.existsQuery(String name)方法新建一个exists查询,传递的name参数是目标字段名称。以下是使用Java客户端构建exists查询的示例:
service层:

	public List<Hotel> existQuery(HotelDocRequest hotelDocRequest) throws IOException {
		//新建搜索请求
		String indexName = hotelDocRequest.getIndexName();
		String propertiesName = hotelDocRequest.getPropertiesName();
		if (CharSequenceUtil.isBlank(indexName)) {
			throw new SearchException("索引名不能为空");
		}
		if (CharSequenceUtil.isBlank(propertiesName)) {
			throw new SearchException("想要查询的字段名不能为空");
		}
		SearchRequest searchRequest = new SearchRequest(indexName);
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		searchSourceBuilder.from(hotelDocRequest.getOffset());
		searchSourceBuilder.size(hotelDocRequest.getLimit());
		searchSourceBuilder.query(QueryBuilders.existsQuery(propertiesName));
		searchRequest.source(searchSourceBuilder);
		return getQueryResult(searchRequest);
	}

controller层:

	@PostMapping("/query/exist")
	public FoundationResponse<List<Hotel>> existQuery(@RequestBody HotelDocRequest hotelDocRequest) {
		try {
			List<Hotel> hotelList = esQueryService.existQuery(hotelDocRequest);
			if (CollUtil.isNotEmpty(hotelList)) {
				return FoundationResponse.success(hotelList);
			} else {
				return FoundationResponse.error(100,"no data");
			}
		} catch (IOException e) {
			log.warn("搜索发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		} catch (Exception e) {
			log.error("服务发生异常,原因为:{}", e.getMessage());
			return FoundationResponse.error(100, e.getMessage());
		}
	}

postman调用即可,比如搜索之前tag字段:
没有搜到,所以报了no data
Elasticsearch(十一)搜索---搜索匹配功能②--range查询和exists查询
如果搜索title,则会将title不为null的值全部搜索出来,由于title不为空的比较多,我这边只查前3条:
Elasticsearch(十一)搜索---搜索匹配功能②--range查询和exists查询文章来源地址https://www.toymoban.com/news/detail-493873.html

到了这里,关于Elasticsearch(十一)搜索---搜索匹配功能②--range查询和exists查询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ES笔记02】ElasticSearch数据库之查询操作(match、must、must_not、should、_source、filter、range、exists、ids、term、terms)

    这篇文章,主要介绍ElasticSearch数据库之查询操作(match、must、must_not、should、_source、filter、range、exists、ids、term、terms)。 目录 一、布尔查询 1.1、主键查询 1.2、两种查询方式 (1)路径参数查询 (2)请求体参数查询 1.3、match查询 (1)match (2)match_all 1.4、过滤字段 1.5、布

    2023年04月09日
    浏览(55)
  • Elasticsearch(十四)搜索---搜索匹配功能⑤--全文搜索

    不同于之前的term。terms等结构化查询,全文搜索首先对查询词进行分析,然后根据查询词的分词结果构建查询。这里所说的全文指的是文本类型数据(text类型),默认的数据形式是人类的自然语言,如对话内容、图书名称、商品介绍和酒店名称等。结构化搜索关注的是数据是

    2024年02月11日
    浏览(52)
  • ElasticSearch系列 - SpringBoot整合ES之全文搜索匹配查询 match

    官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/index.html 权威指南:https://www.elastic.co/guide/cn/elasticsearch/guide/current/structured-search.html 1. 数据准备 官方测试数据下载地址:https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip ,数据量很大,我们自己构造数据吧。 2. m

    2023年04月08日
    浏览(52)
  • Elasticsearch (ES) 搜索引擎: 搜索功能:搜索分页、搜索匹配、全文搜索、搜索建议、字段排序

    原文链接:https://xiets.blog.csdn.net/article/details/132348920 版权声明:原创文章禁止转载 专栏目录:Elasticsearch 专栏(总目录) ES 搜索 API 官网文档:Search APIs 先创建一个索引,并写入一些文档用于搜索示例: 写入一些文档示例: 官网API:The _source option 搜索结果中的文档数据封装

    2024年02月08日
    浏览(53)
  • Elasticsearch查询 - Range查询

    Range查询可以查询一个范围内的文档。它可以用来查询数值型字段、日期型字段、字符串型字段等等。 我们可以使用range查询来查询符合一定范围内的数据,如查询某个价格区间、某个时间段内的数据等等。 查询语法示例 其中, {field} 表示要查询的字段, {lowerBound} 和 {uppe

    2024年02月03日
    浏览(38)
  • elasticsearch之exists查询

    一、exists查询简介 elastic search提供了exists查询,用以返回字段存在值的记录,默认情况下只有字段的值为null或者[]的时候,elasticsearch才会认为字段不存在; exists查询的形式如下,其中field用于指定要查询的字段名字; 二、测试数据准备 我们尽量模拟document中字段可能出现的

    2024年02月02日
    浏览(36)
  • ElasticSearch序列 - SpringBoot整合ES:范围查询 range

    01. ElasticSearch range查询是什么? Elasticsearch 中的 range 查询可以用于查询某个字段在一定范围内的文档。 range 查询可同时提供包含和不包含这两种范围表达式,可供组合的选项如下: gt : 大于(greater than) lt : 小于(less than) gte : = 大于或等于(greater than or equal to) lte : = 小于

    2024年02月09日
    浏览(44)
  • elasticsearch[二]-DSL查询语法:全文检索、精准查询(term/range)、地理坐标查询(矩阵、范围)、复合查询(相关性算法)、布尔查询

    elasticsearch 的查询依然是基于 JSON 风格的 DSL 来实现的。 Elasticsearch 提供了基于 JSON 的 DSL(Domain Specific Language)来定义查询。常见的查询类型包括: 查询所有 :查询出所有数据,一般测试用。例如:match_all 全文检索(full text)查询 :利用分词器对用户输入内容分词,然后去

    2024年01月18日
    浏览(60)
  • ElasticSearch系列 - SpringBoot整合ES:查询字段不为空的文档 exists

    1. ElasticSearch exists 查询是什么 在某些场景下,我们希望找到某个字段不为空的文档,则可以用exists搜索。字段不为空的条件有: 值存在且不是 null; 值不是空数组; 值是数组,但不是 [null] 例如,查询在字段中至少有一个非空值的文档: 这些文档都将匹配上面的查询: ①

    2024年02月06日
    浏览(74)
  • Elasticsearch的全文搜索与匹配

    Elasticsearch是一个开源的搜索和分析引擎,基于Lucene库,用于实现全文搜索和实时分析。它具有高性能、高可扩展性和高可用性,适用于大规模数据的搜索和分析。Elasticsearch的核心功能包括文档存储、搜索引擎、分析引擎和数据可视化。 Elasticsearch的全文搜索功能是其最重要的

    2024年02月22日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包