精通ES+ES大数据查询常见的疑难杂症的解决与实现

news2024/9/23 9:30:02

目录

 什么是BoolQueryBuilder?

简单的复合查询

RestHighLevelClient中的matchQuery与matchPhraseQuery与termQuery的在实际使用中的不同

ES是否能在类型为text的字段的内部使用keyword,如果能这样做的含义是什么?

什么是ES多字段?

ES怎么实现聚合查询?

RestHighLevelClient的subAggregation是什么?干什么用的?

什么是RestHighLevelClient的滚动查询?如何实现?

ES构建简单搜索


 什么是BoolQueryBuilder?

BoolQueryBuilder是该客户端库中的一个查询构建器,用于构建布尔查询(bool query)。 布尔查询是一种复合查询,可以将多个查询条件组合在一起。

BoolQueryBuilder提供了几种方法来构建布尔查询:

1. must(QueryBuilders): 添加一个“必须匹配”(must)的查询条件。这意味着文档必须满足该查询条件才能被返回。 相当于sql中的and

2. mustNot(QueryBuilders): 添加一个“不能匹配”(must not)的查询条件。这意味着文档不能满足该查询条件才能被返回。相当于 is not 

3. should(QueryBuilders): 添加一个“应该匹配”(should)的查询条件。这意味着文档可以满足该查询条件,但不是必须的。 相当与or

4. filter(QueryBuilders): 添加一个“过滤”(filter)的查询条件。与must查询条件类似,但过滤查询不会计算相关性得分,通常用于对结果进行筛选。相当与select 的字段

简单的复合查询

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
    .must(QueryBuilders.termQuery("field1", "value1"))
    .mustNot(QueryBuilders.termQuery("field2", "value2"))
    .should(QueryBuilders.termQuery("field3", "value3"))
    .filter(QueryBuilders.termQuery("field4", "value4"));

// 将boolQuery用于搜索请求
SearchRequest searchRequest = new SearchRequest("indexName");
searchRequest.source(new SearchSourceBuilder().query(boolQuery));

RestHighLevelClient中的matchQuery与matchPhraseQuery与termQuery的在实际使用中的不同

1. matchQuery:  
The matchQuery is a full-text query that analyzes the provided text and generates a query that performs a full-text search on the analyzed text. It is useful when you want to perform a search based on relevance. The matchQuery analyzes the text and generates a set of terms that are used for matching.

翻译:

1.匹配查询:
matchQuery是一个全文查询,用于分析所提供的文本,并生成一个对所分析的文本执行全文搜索的查询。当您想要根据相关性执行搜索时,它非常有用。matchQuery分析文本并生成一组用于匹配的术语。

2. matchPhraseQuery: 
The matchPhraseQuery is similar to the matchQuery, but it analyzes the text as a phrase rather than individual terms. It is useful when you want to search for an exact phrase in the text. The matchPhraseQuery considers the order of the terms and their proximity to each other. 

2.匹配短语查询:
matchPhraseQuery类似于matchQuery,但它将文本作为短语而不是单个术语进行分析。当你想在文本中搜索一个确切的短语时,它很有用。matchPhraseQuery考虑术语的顺序及其彼此之间的接近程度。

termQuery: The termQuery is a query that searches for exact terms in a field. It does not analyze the text and is suitable for searching on keyword fields or fields that are not analyzed. The termQuery matches documents that contain an exact term.

术语查询:
termQuery是一个在字段中搜索精确术语的查询。它不分析文本,适用于搜索关键字字段或未分析的字段。termQuery匹配包含确切术语的文档。

总结:

matchQuery和matchPhraseQuery用于全文搜索并考虑相关性,而termQuery用于精确的术语匹配,不对文本执行分析。您可以根据特定的搜索要求选择适当的查询类型。

ok,

所以简单的来说,

如果搜随机的话请使用matchQuery来完成模糊匹配,

搜索模糊的关键词使用matchPhraseQuery

对指定字段进行精确的分词搜索,适用于关键词精确搜索。

ES是否能在类型为text的字段的内部使用keyword,如果能这样做的含义是什么?

在Elasticsearch中,你可以在类型为"text"的字段内部使用"keyword"。

这种使用方式被称为"multi-fields"(多字段),它允许你在同一个字段上定义多个不同类型的子字段。
 当你在类型为"text"的字段上同时定义一个"keyword"子字段时,它的含义是:
1. "text"类型子字段:该子字段会对文本进行分析,将其拆分为单个词项,并应用分词器和过滤器等分析器组件。这样可以支持全文搜索和相关性评分。
2. "keyword"类型子字段:该子字段会将整个文本作为一个项进行索引和搜索,不进行分词和分析。这样可以实现精确匹配、排序和聚合操作。
 这种使用方式的好处是,你可以在同一个字段上同时支持全文搜索和精确匹配操作,而无需额外定义多个字段。例如,你可以使用"text"类型子字段进行全文搜索,并使用"keyword"类型子字段进行精确匹配或排序。
 以下是一个示例,展示如何在Elasticsearch中定义一个包含"text"和"keyword"子字段的字段:
json
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        }
      }
    }
  }
}
在上面的示例中,"title"字段被定义为"text"类型,并包含一个名为"keyword"的"keyword"类型子字段。这样,你可以同时在"title"字段上进行全文搜索和精确匹配操作。
 总而言之,你可以在类型为"text"的字段内部使用"keyword"子字段,以实现同时支持全文搜索和精确匹配的功能。

实战:

字段

				"agent_name": {
					"type": "text",
					"fields": {
						"keyword": {
							"ignore_above": 256,
							"type": "keyword"
						}
					}
				},

要求精准匹配到agent_name为河南神龙公司的所有信息。

        // 指定索引
        request.indices("smsp_collect_info_new");
        // 构建查询条件
        SearchSourceBuilder searchSourceBuilder=new SearchSourceBuilder();
        // 使用精准分词 查找
        searchSourceBuilder.query(QueryBuilders.termQuery("agent_name.keyword", "河南神龙公司"));
        //放入文档中
        request.source(searchSourceBuilder);
        //远程查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //获取结果
        SearchHit[] searchHits = response.getHits().getHits();
        for (SearchHit hit : searchHits) {
            System.out.println(hit.getSourceAsMap().get("agent_name"));
        }

这里的agent_name字段就是运用了多字段的思想/方式。

什么是ES多字段?

ES多字段(Multi-fields)是Elasticsearch中的一个概念,它允许在一个字段上定义多个不同类型的子字段。每个子字段可以根据不同的需求进行不同的处理和索引,以便在搜索和聚合时提供更灵活的功能。
 使用多字段的主要目的是在同一个字段上同时支持多种查询需求。例如,你可能想要在一个字段上进行全文搜索、精确匹配和排序等操作。通过使用多字段,你可以根据不同的查询需求定义不同类型的子字段,从而在每个子字段上使用适当的查询方式。
 多字段可以在映射(mapping)中定义。以下是一个示例,展示如何在Elasticsearch中定义一个包含多字段的字段:
json
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          },
          "english": {
            "type": "text",
            "analyzer": "english"
          }
        }
      }
    }
  }
}
在上面的示例中,"title"字段被定义为"text"类型,并包含两个子字段:"keyword"和"english"。其中,"keyword"子字段是"keyword"类型,用于精确匹配和排序,而"english"子字段是"text"类型,并使用英文分析器进行全文搜索。
 通过使用多字段,你可以根据不同的查询需求选择适当的子字段进行搜索、排序和聚合,从而提供更灵活和准确的搜索体验。
 总而言之,ES多字段是在一个字段上定义多个不同类型的子字段,用于在不同的查询需求下提供灵活的搜索和聚合功能。

ES怎么实现聚合查询?

主要是通过AggregationBuilders来进行聚合条件的构建,然后通过aggregation方法将AggregationBuilders拼接到SearchSourceBuilder 中实现的。如果有子聚合是通过subaggregation方法进行拼装的。

聚合查询的类型

- Range Aggregation:按指定的范围对字段进行聚合,比如按价格范围聚合商品。

- Date Histogram Aggregation:按指定的时间间隔对日期字段进行聚合,比如按月份聚合销售数据。

- Histogram Aggregation:按指定的数值间隔对数值字段进行聚合,比如按价格区间聚合商品。

- Terms Aggregation:对字段进行词条聚合,类似于SQL中的GROUP BY操作。

- Avg Aggregation:计算字段的平均值。

- Sum Aggregation:计算字段的总和。

- Max Aggregation:计算字段的最大值。

- Min Aggregation:计算字段的最小值。

- Cardinality Aggregation:计算字段的基数(不重复值的数量)。

查询+分组聚合实战

public void GroupSearch() throws IOException {
        SearchRequest request = new SearchRequest();

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        request.indices("smsp_collect_info_new");
        // 模糊分词查询
        searchSourceBuilder.query(QueryBuilders.matchQuery("province", "河南"));
        // 分组聚合查询
        searchSourceBuilder.aggregation(AggregationBuilders
                .terms("your_agg_name")
                .field("agent_name.keyword")
                .subAggregation(AggregationBuilders.count("count_number")
                        // 指定返回的桶的最大数量为10000
                        .field("company.keyword")).size(10000));

        //放入文档中
        request.source(searchSourceBuilder);
        //远程查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 获取所有的桶
        Terms termsAggregation = response.getAggregations().get("your_agg_name");
        for (Terms.Bucket bucket : termsAggregation.getBuckets()) {
            // 获得每次聚合的key的值
            System.out.println("当前的key为:"+bucket.getKeyAsString());
            ValueCount countAggregation =bucket.getAggregations().get("count_number");
            System.out.println("当前键下的聚合属性的总和,"+countAggregation.getValue());
        }
    }

RestHighLevelClient的subAggregation是什么?干什么用的?

RestHighLevelClient的subAggregation是用于在Elasticsearch中进行嵌套聚合操作的功能。在Elasticsearch中,聚合是一种用于对数据进行分组、过滤和计算的功能,可以根据不同的聚合类型对字段进行统计、计算平均值、求和等操作。

subAggregation允许在一个聚合操作的结果上进行进一步的嵌套聚合操作。

通过使用subAggregation,可以对聚合结果进行更细粒度的分析和处理。

例如,可以在terms聚合的结果上进行子聚合,对每个聚合桶进行更深入的统计。

以下是一个使用RestHighLevelClient进行subAggregation的示例代码:

RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(new HttpHost("localhost", 9200, "http")));
 SearchRequest searchRequest = new SearchRequest("your_index_name"); // 替换为实际的索引名
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
 // 添加主聚合
TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("my_terms_agg")
        .field("your_field_name"); // 替换为实际的字段名
 // 添加子聚合
MaxAggregationBuilder subAggregationBuilder = AggregationBuilders.max("my_max_agg")
        .field("your_nested_field_name"); // 替换为实际的嵌套字段名
aggregationBuilder.subAggregation(subAggregationBuilder);
 searchSourceBuilder.aggregation(aggregationBuilder);
searchRequest.source(searchSourceBuilder);
 try {
    SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
     // 解析聚合结果
    Terms termsAggregation = searchResponse.getAggregations().get("my_terms_agg");
    for (Terms.Bucket bucket : termsAggregation.getBuckets()) {
        String key = bucket.getKeyAsString();
        Max maxAggregation = bucket.getAggregations().get("my_max_agg");
        double max = maxAggregation.getValue();
         // 处理聚合结果
        System.out.println("Bucket Key: " + key);
        System.out.println("Max Value: " + max);
    }
} catch (IOException e) {
    e.printStackTrace();
}
 client.close();

什么是RestHighLevelClient的滚动查询?如何实现?

RestHighLevelClient的滚动查询是一种用于在Elasticsearch中检索大量数据的机制。它允许您通过多个请求迭代地获取结果集,而不是一次性获取所有结果。滚动查询适用于需要处理大量数据的情况,例如导出数据、数据分析等。
 与其他查询方式相比,滚动查询具有以下优势:
1. 可以处理大量数据:滚动查询适用于处理超过单个请求的结果集大小限制的情况。它允许您按需获取数据,而不会因为数据量过大而导致请求失败或性能下降。
2. 节省内存:滚动查询通过每次返回一小批结果并在服务器端维护滚动上下文来减少内存消耗。这使得在处理大量数据时,不需要将所有结果加载到内存中,从而节省了内存资源。
3. 支持持续查询:滚动查询的结果可以被持续使用,即使在处理期间索引中的数据发生了变化。您可以使用滚动上下文来保持查询的一致性,而不受索引更新的影响。
4. 支持并发处理:通过使用滚动查询,您可以并发地处理多个滚动上下文,从而提高查询的吞吐量和效率。
 需要注意的是,滚动查询也有一些限制和注意事项:
1. 滚动查询会占用服务器资源:由于滚动上下文需要在服务器端维护,因此会占用一定的内存和计算资源。在设计滚动查询时,需要考虑服务器的可用资源以及查询的并发性能。
2. 滚动查询的结果可能不是实时的:如果在滚动查询期间索引中的数据发生了变化,滚动查询的结果可能不会反映最新的数据。因此,在滚动查询中处理数据时,需要注意数据的一致性和实时性。
 总之,RestHighLevelClient的滚动查询是一种强大的机制,可以高效地处理大量数据。它提供了灵活的分批获取结果的方式,适用于需要处理大数据量的场景。

实现:

public void ScrollSearch() throws IOException {
        SearchRequest request = new SearchRequest();
        //失效时间为10min
        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(10));
        //封存快照
        request.scroll(scroll);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        request.indices("smsp_collect_info_new");
        searchSourceBuilder.query(QueryBuilders.matchQuery("province", "黑龙江"));
        // 每次查询2000个,是滚动查询条数的步长
        searchSourceBuilder.size(2000);
        //放入文档中
        request.source(searchSourceBuilder);
        //远程查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHit[] searchHits = response.getHits().getHits();
        //处理第一次的响应结果
        for (SearchHit hit : searchHits) {
            String province = hit.getSourceAsMap().get("province").toString();
            System.out.println(province);
            // 处理每个查询结果
        }
        // 获取第一次的滚动id
        String scrollId = response.getScrollId();
        while (searchHits.length > 0) {
            // 每循环一次构建一个新的滚动请求。
            SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
            scrollRequest.scroll(TimeValue.timeValueMinutes(1));
            response = client.scroll(scrollRequest, RequestOptions.DEFAULT);
            // 获取新的滚动请求的滚动id
            scrollId = response.getScrollId();
            searchHits = response.getHits().getHits();
            // 处理下一批查询结果
            for (SearchHit hit : searchHits) {
                String province = hit.getSourceAsMap().get("province").toString();
                System.out.println(province);
                // 处理每个查询结果
            }
        }

    }

ES构建简单搜索

使用模糊匹配

public void simpleSearch() throws IOException {
        SearchRequest request = new SearchRequest();
        // 指定索引
        request.indices("smsp_collect_info_new");
        // 构建查询条件 查询某城市
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("city", "郑州"));
        //放入文档中
        request.source(searchSourceBuilder);
        //远程查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //获取结果
        SearchHit[] searchHits = response.getHits().getHits();
        for (SearchHit hit : searchHits) {
            System.out.println(hit.getSourceAsMap().get("city"));
        }
    }

 使用精准匹配

    // 单条件精准查询
    public void simpleSearchUseTerm() throws IOException {
        SearchRequest request = new SearchRequest();
        // 指定索引
        request.indices("smsp_collect_info_new");
        // 构建查询条件 查询某城市
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 使用精准分词 查找
        searchSourceBuilder.query(QueryBuilders.termQuery("agent_name.keyword", "河南神龙公司"));
        //放入文档中
        request.source(searchSourceBuilder);
        //远程查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //获取结果
        SearchHit[] searchHits = response.getHits().getHits();
        for (SearchHit hit : searchHits) {
            System.out.println(hit.getSourceAsMap().get("agent_name"));
        }
    }

 

 

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

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

相关文章

BES 的BLE MTU设置

1 BES BLE MTU 一个默认的MTU大小,通常为23字节,通过协商,可以使用更大的MTU,最高可达512字节, 2 协商方法

leetcode146.手撸 LRU 算法(java)

LRU 缓存 LRU 缓存题目描述LRU 介绍LRU 算法设计代码实现 单调栈算法 LRU 缓存 来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/lru-cache 题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实…

HNU-小学期工训-STC-B测试记录表

说明1“分类I”为检测电路板硬件测试案例,“分类ⅡI、Ⅲ、IV”为不同层次综合应用案例。"分类1、Ⅱ、Ⅲ”必做,“分类TV”选做。 说明2:“测试/故障现象记录”栏:记录实际测量效果并与案例说明对比,并记录;有故障时,记录所见…

《AutoSar实战》读写DID之一:CDD准备

文章目录 前言一、1.新建DID1,使用 **CANdelaStudio** 软件打开工程中的CDD文件并创建DID1) 创建DID2) 详细配置DID3)配置读写服务权限 二、同步更新工具链配置1 更新文件并检查1) 更新CDD文件2)检查更新结果 总结 前言 本章节主…

大型语言模型与知识图谱协同研究综述:两大技术优势互补

机器之心报道 编辑:杜伟 多图综述理清当前研究现状,这篇 29 页的论文值得一读。 大型语言模型(LLM)已经很强了,但还可以更强。通过结合知识图谱,LLM 有望解决缺乏事实知识、幻觉和可解释性等诸多问题&am…

记录一下kibana启动连接报错问题(kibana server is not ready yet)

记录一下kibana启动连接报错问题(kibana server is not ready yet) 今天启动kibana出现该问题 先去看了看是否是elasticsearch连接出错 启动了容器 docker start elasticsearch docker start kibana进入了kibana容器 docker exec -it kibana bash进行了下面的操作&#xf…

注册微信小程序平台安装微信小程序开发工具(详细教程)

首先我们先去微信小程序平台注册账号,下面是网址 首页 | 微信开放社区 进入后,使用手机扫描登录,然后,选择小程序,选择个体——填写个人信息——进入到开发者平台(相信这里对一个开发者很简单了吧&#xff…

API安全测试检查项小结

现如今开发基本上都是前后端分离,相比前端,后端的测试是最容易发现一些底层bug, 修复成本也低。今天主要聊聊接口的安全测试,以及常见的漏洞。 一、逻辑越权类 可以分为两类:平行越权:权限类型不变,权限对…

单线程JavaScript为何如此高效

什么是js执行机制 JavaScript 的执行机制指的是 JavaScript 代码在运行时的工作方式和顺序。它涉及以下几个关键概念: 单线程:JavaScript 是一门单线程的编程语言,意味着它只有一个主线程用于执行代码。这意味着 JavaScript 中的代码是按顺序…

编程(43)----------ConcurrentHashMap

在多线程中使用哈希表, 首先是不能使用HashMap的. 因为其本身并非线程安全. 与其相反HashTable则是安全的. 其原因在于本身给关键的方法加了锁. 但即便如此, 与HashTable相比, 更推荐使用ConcurrentHashMap. 其原因在于, 它在HashTable的基础上做了较多的优化: 上述提到, Hash…

自从前端用上了低代码,开发速度直接起飞

作为前端工作人员,我们都深知在这个快速发展的时代里,不断学习和掌握前沿技术是至关重要的。随着互联网的不断革新和新兴技术的崛起,我们需要保持敏锐的触角,紧跟潮流,才能在竞争激烈的市场中保持领先地位。 一直以来&…

MAC电脑垃圾好用的文件清理软件CleanMyMac X

古语云:“工欲善其事,必先利其器。”因此,一个运行流畅的Mac更能使我们的工作事半功倍。但又是什么导致电脑的运行不流畅呢? 其实这大多还是缓存垃圾过多、内存不足的原因。尝试安装了许多的垃圾文件清理软件,垃圾没有…

HashMap 为什么不能一边遍历一遍删除

前段时间,同事在代码中 KW 扫描的时候出现这样一条: 上面出现这样的原因是在使用 foreach 对 HashMap 进行遍历时,同时进行 put 赋值操作会有问题,异常 ConcurrentModificationException。 于是帮同简单的看了一下,印象…

为什么Qt成为工业软件开发的首选框架?

工业软件开发中使用Qt的主要原因有以下几点: 跨平台性:Qt是一个跨平台的C应用程序开发框架,可以在多个操作系统上运行,包括Windows、macOS、Linux等。这种跨平台性使得开发人员能够使用相同的代码库创建适用于不同操作系统的应用程…

Github-Readme-Stats 简明教程

注:本篇文章首发于 博客园sarexpine 为保持阅读的舒适性,可以选择移步至 博客园sarexpine 阅读,日后的文章将首发于 博客园sarexpine 平台,谢谢! 1. 更新 Readme 文件 在你想要放置 Readme-WakaTime 的位置中放置以下…

Nginx【Nginx场景实践(动静分离、动静分离实战、缓存机制)】(十)-全面详解(学习总结---从入门到深化)

目录 Nginx场景实践_动静分离 Nginx场景实践_动静分离实战 Nginx场景实践_缓存机制 Nginx场景实践_动静分离 Nginx动静分离简单来说就是把动态和静态请求分开,不能理解成只是单纯的把动态页面和静态页面物理分离。严格意义上说应该是动态请求和静态请求分开&…

@Transaction事务导致的mysql连接耗尽源码分析

背景: Transaction注解是我们在日常的写代码过程中最常使用的事务注解了,本文就从spring源码的角度解析下这个注解的执行过程,以便分析为什么使用事务比正常的单sql执行更容易导致连接池耗尽 源码追踪: 本文假定使用PROPAGATIO…

音频怎么转文字?试试这三个简单的方法吧!

有时候我们会遇到一些比较重要的会议、讲座或者演讲,如果我们能够将这些声音记录下来,并将其转换为文字,就可以更加方便地保存和管理这些信息。这样,我们就不用再去听录音了,只需要看文字就可以了。此外,录…

智能指针的deleter机制

一、介绍 智能指针的deleter机制是指,当智能指针的引用计数降为0时,智能指针会自动调用一个指定的析构函数(deleter)来释放所管理的内存。这个析构函数通常是一个函数对象,可以是一个函数指针、一个lambda表达式或者一…

青少年机器人技术一级考试备考重点(四):功与能量以及常用传动装置

随着机器人技术的飞速发展,越来越多的青少年开始关注并参与其中。青少年机器人技术考试作为一项评估学生机器人技术水平的重要考试,备受广大青少年和家长的关注。为了更好地备战青少年机器人技术一级考试,了解考试的学习要点和备考重点是非常…