最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Elasticsearch安裝?+?CRUD?+?查詢實戰(zhàn)指南

 更新時間:2026年03月16日 10:21:01   作者:阿杰真不會敲代碼  
Elasticsearch是基于Lucene的分布式全文搜索引擎,支持近實時搜索、海量數(shù)據(jù)存儲、高可用集群、RESTful?API,廣泛用于日志分析、商品搜索、數(shù)據(jù)可視化等場景,本文給大家介紹Elasticsearch安裝+CRUD+查詢實戰(zhàn)指南,感興趣的朋友跟隨小編一起看看吧

一、Elasticsearch 是什么??

Elasticsearch(簡稱 ES) 是基于 Lucene 的分布式全文搜索引擎,支持近實時搜索、海量數(shù)據(jù)存儲、高可用集群、RESTful API,廣泛用于日志分析、商品搜索、數(shù)據(jù)可視化等場景。?

在搜索時為什么我們要用 Elasticsearch,而不是 MySQL 模糊匹配?

在實際業(yè)務中,商品搜索、日志檢索、全文搜索 這些場景,MySQL 根本扛不住。

1. MySQL 的like '%關(guān)鍵詞%'為什么慢?

  • 無法走索引,必須全表掃描
  • 數(shù)據(jù)量越大,速度越慢
  • 不支持分詞,不支持相關(guān)性打分
  • 不支持高亮、同義詞、拼音搜索

簡單說:數(shù)據(jù)量一大,like 查詢直接拖垮數(shù)據(jù)庫。

2. Elasticsearch 為什么快?—— 倒排索引原理

ES 快的核心原因只有一個:它用了 倒排索引(Inverted Index)。

我用最簡單的方式講清楚:

正常數(shù)據(jù)庫(正排索引)

文檔1 → 我喜歡華為手機

文檔2 → 華為手機信號好

文檔3 → 蘋果手機也不錯

倒排索引(關(guān)鍵詞 → 文檔)

華為 → 文檔1、文檔2

手機 → 文檔1、文檔2、文檔3

蘋果 → 文檔3 喜歡 → 文檔1

當你搜索:“華為”

ES 不需要掃全表,直接查倒排索引:華為 → 文檔 1、文檔 2直接返回,毫秒級響應。

3. 倒排索引三大優(yōu)勢

  1. 檢索極快:不需要全表掃描
  2. 支持分詞:把一句話切成詞語
  3. 相關(guān)性打分:最匹配的排前面

MySQL 適合存數(shù)據(jù),Elasticsearch 適合搜數(shù)據(jù)。

MySQL 用 B+ 樹,適合精確查詢。

Elasticsearch 用倒排索引,適合全文檢索。

Elasticsearch核心概念?

  • 索引(Index):對應 MySQL 的數(shù)據(jù)庫?
  • 文檔(Document):對應 MySQL 的行數(shù)據(jù)?
  • 映射(Mapping):對應 MySQL 的表結(jié)構(gòu)?
  • 分片 / 副本:保證分布式存儲與高可用

文檔數(shù)據(jù)會被序列化為json格式后存儲在elasticsearch

我們統(tǒng)一的把mysql與elasticsearch的概念做一下對比

Kibana是elastic公司提供的用于操作Elasticsearch的可視化控制臺。它的功能非常強大,包括:

  • 對Elasticsearch數(shù)據(jù)的搜索、展示
  • 對Elasticsearch數(shù)據(jù)的統(tǒng)計、聚合,并形成圖形化報表、圖形
  • 對Elasticsearch的集群狀態(tài)監(jiān)控
  • 它還提供了一個開發(fā)控制臺(DevTools),在其中對Elasticsearch的Restful的API接口提供了語法提示

elasticsearch安裝

通過下面的Docker命令即可安裝單機版本的elasticsearch:

docker run -d \
  --name es \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  -e "discovery.type=single-node" \
  -v es-data:/usr/share/elasticsearch/data \
  -v es-plugins:/usr/share/elasticsearch/plugins \
  --privileged \
  --network hm-net \
  -p 9200:9200 \
  -p 9300:9300 \
  elasticsearch:7.12.1

訪問9200端口,即可看到響應的Elasticsearch服務的基本信息:

安裝kibana

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=hm-net \
-p 5601:5601  \
kibana:7.12.1

訪問5601端口,即可看到控制臺頁面:

ik分詞器

Elasticsearch的關(guān)鍵就是倒排索引,而倒排索引依賴于對文檔內(nèi)容的分詞,而分詞則需要高效、精準的分詞算法,IK分詞器就是這樣一個中文分詞算法。

安裝:

docker exec -it es ./bin/elasticsearch-plugin  install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip

IK分詞器包含兩種模式:

  • ik_smart:智能語義切分
  • ik_max_word:最細粒度切分

詞典:隨著互聯(lián)網(wǎng)的發(fā)展出現(xiàn)了很多新的詞語,在原有的詞匯列表中并不存在,IK分詞器無法對這些詞匯分詞,要想正確分詞,IK分詞器的詞庫也需要不斷的更新,IK分詞器提供了擴展詞匯的功能

在分詞器的配置目錄下

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 擴展配置</comment>
        <!--用戶可以在這里配置自己的擴展字典 *** 添加擴展詞典-->
        <entry key="ext_dict">ext.dic</entry>
</properties>

改目錄下目錄新建一個 ext.dic,然后在里面添加新的詞匯,重啟后ik分詞器就能正確識別ext.dic的這些單詞

CRUD操作:

由于Elasticsearch采用的是Restful風格的API,因此其請求方式和路徑相對都比較規(guī)范,而且請求參數(shù)也都采用JSON風格。

我們直接基于Kibana的DevTools來編寫請求做測試,由于有語法提示,會非常方便。

.創(chuàng)建索引庫和映射

基本語法

  • 請求方式:PUT
  • 請求路徑:/索引庫名,可以自定義
  • 請求參數(shù):mapping映射
PUT /索引庫名稱
{
  "mappings": {
    "properties": {
      "字段名":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{
        "properties": {
          "子字段": {
            "type": "keyword"
          }
        }
      },
      // ...略
    }
  }
}

查詢索引庫

基本語法

  • 請求方式:GET
  • 請求路徑:/索引庫名
  • 請求參數(shù):無

比如:GET /item

修改索引庫

倒排索引結(jié)構(gòu)雖然不復雜,但是一旦數(shù)據(jù)結(jié)構(gòu)改變(比如改變了分詞器),就需要重新創(chuàng)建倒排索引,這簡直是災難。因此索引庫一旦創(chuàng)建,無法修改mapping。

雖然無法修改mapping中已有的字段,但是卻允許添加新的字段到mapping中,因為不會對倒排索引產(chǎn)生影響。因此修改索引庫能做的就是向索引庫中添加新字段,或者更新索引庫的基礎(chǔ)屬性。

語法:

PUT /索引庫名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

刪除索引庫

語法:

  • 請求方式:DELETE
  • 請求路徑:/索引庫名
  • 請求參數(shù):無

文檔操作

有了索引庫,接下來就可以向索引庫中添加數(shù)據(jù)了。

4.1 新增文檔(指定 ID)?

PUT /product/_doc/1?
{?
"id": 1,?
"name": "華為Mate70",?
"price": 5999,?
"category": "手機"?
}?

新增文檔(自動 ID)

POST /product/_doc?
{?
  "id": 2,?
  "name": "小米14",?
  "price": 4299,?
  "category": "手機"?
}

4.3 查詢文檔(根據(jù) ID)

GET /product/_doc/1

全量更新文檔(相當于覆蓋原文檔)

PUT /product/_doc/1
{
  "id": 1,
  "name": "華為Mate70 Pro",
  "price": 6999,
  "category": "手機"
}

局部更新文檔(推薦)

POST /product/_update/1
{
  "doc": {
    "price": 6799
  }
}

刪除文檔

DELETE /product/_doc/1

批處理

POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
  • index代表新增操作

    • _index:指定索引庫名

    • _id指定要操作的文檔id

    • { "field1" : "value1" }:則是要新增的文檔內(nèi)容

  • delete代表刪除操作

    • _index:指定索引庫名

    • _id指定要操作的文檔id

  • update代表更新操作

    • _index:指定索引庫名

    • _id指定要操作的文檔id

    • { "doc" : {"field2" : "value2"} }:要更新的文檔字段

總結(jié)

  • 創(chuàng)建文檔:POST /{索引庫名}/_doc/文檔id { json文檔 }

  • 查詢文檔:GET /{索引庫名}/_doc/文檔id

  • 刪除文檔:DELETE /{索引庫名}/_doc/文檔id

  • 修改文檔:

    • 全量修改:PUT /{索引庫名}/_doc/文檔id { json文檔 }

    • 局部修改:POST /{索引庫名}/_update/文檔id { "doc": {字段}}

在java中訪問客戶端

引入依賴

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

因為SpringBoot默認的ES版本是7.17.10,所以我們需要覆蓋默認的ES版本

  <properties>
      <maven.compiler.source>11</maven.compiler.source>
      <maven.compiler.target>11</maven.compiler.target>
      <elasticsearch.version>7.12.1</elasticsearch.version>
  </properties>

初始化RestHighLevelClient:

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        HttpHost.create("http://192.168.150.101:9200")
));
package com.hmall.item.es;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;

public class IndexTest {

    private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.150.101:9200")
        ));
    }

    @Test
    void testConnect() {
        System.out.println(client);
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

RestClient操作索引庫

代碼分為三步:

  • 1)創(chuàng)建Request對象。

    • 因為是創(chuàng)建索引庫的操作,因此Request是CreateIndexRequest

  • 2)添加請求參數(shù)

    • 其實就是Json格式的Mapping映射參數(shù)。因為json字符串很長,這里是定義了靜態(tài)字符串常量MAPPING_TEMPLATE,讓代碼看起來更加優(yōu)雅。

  • 3)發(fā)送請求

    • client.indices()方法的返回值是IndicesClient類型,封裝了所有與索引庫操作有關(guān)的方法。例如創(chuàng)建索引、刪除索引、判斷索引是否存在等

RestClient操作文檔

新增文檔

  // 1.準備Request對象
    IndexRequest request = new IndexRequest("items").id(itemDoc.getId());
    // 2.準備Json文檔
    request.source(doc, XContentType.JSON);
    // 3.發(fā)送請求
    client.index(request, RequestOptions.DEFAULT);
  • 1)創(chuàng)建Request對象,這里是IndexRequest,因為添加文檔就是創(chuàng)建倒排索引的過程

  • 2)準備請求參數(shù),本例中就是Json文檔

  • 3)發(fā)送請求

查詢文檔

刪除文檔

@Test
void testDeleteDocument() throws IOException {
    // 1.準備Request,兩個參數(shù),第一個是索引庫名,第二個是文檔id
    DeleteRequest request = new DeleteRequest("item", "100002644680");
    // 2.發(fā)送請求
    client.delete(request, RequestOptions.DEFAULT);
}

修改文檔

修改我們講過兩種方式:

  • 全量修改:本質(zhì)是先根據(jù)id刪除,再新增

  • 局部修改:修改文檔中的指定字段值

在RestClient的API中,全量修改與新增的API完全一致,判斷依據(jù)是ID:

  • 如果新增時,ID已經(jīng)存在,則修改

  • 如果新增時,ID不存在,則新增

這里不再贅述,我們主要關(guān)注局部修改的API即可。

.批量導入文檔

@Test
void testBulk() throws IOException {
    // 1.創(chuàng)建Request
    BulkRequest request = new BulkRequest();
    // 2.準備請求參數(shù)
    request.add(new IndexRequest("items").id("1").source("json doc1", XContentType.JSON));
    request.add(new IndexRequest("items").id("2").source("json doc2", XContentType.JSON));
    // 3.發(fā)送請求
    client.bulk(request, RequestOptions.DEFAULT);
}

總結(jié)

  • 初始化RestHighLevelClient

  • 創(chuàng)建XxxRequest。

    • XXX是IndexGet、Update、Delete、Bulk

  • 準備參數(shù)(Index、Update、Bulk時需要)

  • 發(fā)送請求。

    • 調(diào)用RestHighLevelClient#.xxx()方法,xxx是indexget、update、delete、bulk

  • 解析結(jié)果(Get時需要)

DSL查詢

在 Elasticsearch 中,所有復雜查詢都是通過 DSL(Domain Specific Language) 來實現(xiàn)的。簡單說:DSL = 用 JSON 寫查詢語句

所有查詢都分為兩類:

(1)查詢上下文(Query Context)

計算相關(guān)性分數(shù)(_score)用于:全文搜索、模糊匹配例:match、match_phrase、multi_match

(2)過濾上下文(Filter Context)

不計算分數(shù),只判斷 是 / 否速度極快,會自動緩存用于:精確匹配、范圍、布爾過濾例:term、range、bool filter

最常用 DSL 查詢

match 全文檢索

對字段分詞后匹配

{
  "query": {
    "match": {
      "name": "拉桿箱"
    }
  }
}

查詢結(jié)果一般格式

term 精確匹配(不分詞)

用于 keyword、數(shù)字、布爾

{
  "query": {
    "term": {
      "category": "手機"
    }
  }
}

range 范圍查詢

{
  "query": {
    "range": {
      "price": {
        "gte": 3000,
        "lte": 8000
      }
    }
  }
}

搜索的關(guān)鍵字高亮

GET /{索引庫名}/_search
{
  "query": {
    "match": {
      "搜索字段": "搜索關(guān)鍵字"
    }
  },
  "highlight": {
    "fields": {
      "高亮字段名稱": {
        "pre_tags": "<em>",
        "post_tags": "</em>"
      }
    }
  }
}

bool :組合查詢包含四個子句:

  • must:必須滿足(算分)
  • should:滿足任意一個
  • must_not:必須不滿足
  • filter:必須滿足(過濾,不計分

示例

{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "手機" } }
      ],
      "filter": [
        { "range": { "price": { "gte": 2000 } } }
      ]
    }
  }
}

分頁、排序、指定返回字段

{
  "from": 0,
  "size": 10,
  "_source": ["name", "price"],
  "sort": [
    { "price": { "order": "desc" } }
  ],
  "query": {
    "match_all": {}
  }
}

總結(jié)

查詢的DSL是一個大的JSON對象,包含下列屬性:

  • query:查詢條件

  • fromsize:分頁條件

  • sort:排序條件

  • highlight:高亮條件

Java中RestClient查詢

  • 第一步,創(chuàng)建SearchRequest對象,指定索引庫名

  • 第二步,利用request.source()構(gòu)建DSL,DSL中可以包含查詢、分頁、排序、高亮等

    • query():代表查詢條件,利用QueryBuilders.matchAllQuery()構(gòu)建一個match_all查詢的DSL

  • 第三步,利用client.search()發(fā)送請求,得到響應

request.source(),它構(gòu)建的就是DSL中的完整JSON參數(shù)。其中包含了query、sort、fromsize、highlight等所有功能

QueryBuilders,其中包含了葉子查詢、復合查詢

解析響應結(jié)果

elasticsearch返回的結(jié)果是一個JSON字符串,結(jié)構(gòu)包含:

  • hits:命中的結(jié)果

    • total:總條數(shù),其中的value是具體的總條數(shù)值

    • max_score:所有結(jié)果中得分最高的文檔的相關(guān)性算分

    • hits:搜索結(jié)果的文檔數(shù)組,其中的每個文檔都是一個json對象

      • _source:文檔中的原始數(shù)據(jù),也是json對象

因此,我們解析響應結(jié)果,就是逐層解析JSON字符串,流程如下:

  • SearchHits:通過response.getHits()獲取,就是JSON中的最外層的hits,代表命中的結(jié)果

    • SearchHits#getTotalHits().value:獲取總條數(shù)信息

    • SearchHits#getHits():獲取SearchHit數(shù)組,也就是文檔數(shù)組

      • SearchHit#getSourceAsString():獲取文檔結(jié)果中的_source,也就是原始的json文檔數(shù)據(jù)

葉子查詢

所有的查詢條件都是由QueryBuilders來構(gòu)建的,葉子查詢也不例外。因此整套代碼中變化的部分僅僅是query條件構(gòu)造的方式,其它不動。

match查詢:

@Test
void testMatch() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    request.source().query(QueryBuilders.matchQuery("name", "脫脂牛奶"));
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}

multi_match查詢

@Test
void testMultiMatch() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    request.source().query(QueryBuilders.multiMatchQuery("脫脂牛奶", "name", "category"));
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}

還有range查詢:

@Test
void testRange() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    request.source().query(QueryBuilders.rangeQuery("price").gte(10000).lte(30000));
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}

term查詢:

@Test
void testTerm() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    request.source().query(QueryBuilders.termQuery("brand", "華為"));
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}

復合查詢

復合查詢也是由QueryBuilders來構(gòu)建,我們以bool查詢?yōu)槔?,DSL和JavaAPI的對比如圖:

@Test
void testBool() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    // 2.1.準備bool查詢
    BoolQueryBuilder bool = QueryBuilders.boolQuery();
    // 2.2.關(guān)鍵字搜索
    bool.must(QueryBuilders.matchQuery("name", "脫脂牛奶"));
    // 2.3.品牌過濾
    bool.filter(QueryBuilders.termQuery("brand", "德亞"));
    // 2.4.價格過濾
    bool.filter(QueryBuilders.rangeQuery("price").lte(30000));
    request.source().query(bool);
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}

排序和分頁

@Test
void testPageAndSort() throws IOException {
    int pageNo = 1, pageSize = 5;

    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    // 2.1.搜索條件參數(shù)
    request.source().query(QueryBuilders.matchQuery("name", "脫脂牛奶"));
    // 2.2.排序參數(shù)
    request.source().sort("price", SortOrder.ASC);
    // 2.3.分頁參數(shù)
    request.source().from((pageNo - 1) * pageSize).size(pageSize);
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}

高亮

@Test
void testHighlight() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.組織請求參數(shù)
    // 2.1.query條件
    request.source().query(QueryBuilders.matchQuery("name", "脫脂牛奶"));
    // 2.2.高亮條件
    request.source().highlighter(
            SearchSourceBuilder.highlight()
                    .field("name")
                    .preTags("<em>")
                    .postTags("</em>")
    );
    // 3.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 4.解析響應
    handleResponse(response);
}
private void handleResponse(SearchResponse response) {
    SearchHits searchHits = response.getHits();
    // 1.獲取總條數(shù)
    long total = searchHits.getTotalHits().value;
    System.out.println("共搜索到" + total + "條數(shù)據(jù)");
    // 2.遍歷結(jié)果數(shù)組
    SearchHit[] hits = searchHits.getHits();
    for (SearchHit hit : hits) {
        // 3.得到_source,也就是原始json文檔
        String source = hit.getSourceAsString();
        // 4.反序列化
        ItemDoc item = JSONUtil.toBean(source, ItemDoc.class);
        // 5.獲取高亮結(jié)果
        Map<String, HighlightField> hfs = hit.getHighlightFields();
        if (CollUtils.isNotEmpty(hfs)) {
            // 5.1.有高亮結(jié)果,獲取name的高亮結(jié)果
            HighlightField hf = hfs.get("name");
            if (hf != null) {
                // 5.2.獲取第一個高亮結(jié)果片段,就是商品名稱的高亮值
                String hfName = hf.getFragments()[0].string();
                item.setName(hfName);
            }
        }
        System.out.println(item);
    }
}

數(shù)據(jù)聚合

聚合 = 對數(shù)據(jù)進行統(tǒng)計、分組、求和、平均值、最大值、最小值、計數(shù)。

你可以把它理解為:MySQL 的 group by + sum + avg + count 超級加強版。

聚合的基本結(jié)構(gòu)

{
  "size": 0,       // 不返回原始數(shù)據(jù),只返回統(tǒng)計結(jié)果
  "aggs": {        // 聚合固定寫 aggs
    "自定義名稱": {
      "聚合類型": {
        "field": "字段名"
      }
    }
  }
}

聚合常見的有三類:

  • 桶(Bucket聚合:用來對文檔做分組

    • TermAggregation:按照文檔字段值分組,例如按照品牌值分組、按照國家分組

    • Date Histogram:按照日期階梯分組,例如一周為一組,或者一月為一組

  • 度量(Metric聚合:用以計算一些值,比如:最大值、最小值、平均值等

    • Avg:求平均值

    • Max:求最大值

    • Min:求最小值

    • Stats:同時求max、minavg、sum

  • 管道(pipeline聚合:其它聚合的結(jié)果為基礎(chǔ)做進一步運算

注意:參加聚合的字段必須是keyword、日期、數(shù)值、布爾類型

.Bucket聚合

例如我們要統(tǒng)計所有商品中共有哪些商品分類,其實就是以分類(category)字段對數(shù)據(jù)分組。category值一樣的放在同一組,屬于Bucket聚合中的Term聚合。

GET /items/_search
{
  "size": 0, 
  "aggs": {
    "category_agg": {
      "terms": {
        "field": "category",
        "size": 20
      }
    }
  }
}
  • size:設(shè)置size為0,就是每頁查0條,則結(jié)果中就不包含文檔,只包含聚合

  • aggs:定義聚合

    • category_agg:聚合名稱,自定義,但不能重復

      • terms:聚合的類型,按分類聚合,所以用term

        • field:參與聚合的字段名稱

        • size:希望返回的聚合結(jié)果的最大數(shù)量

查詢的結(jié)果:

嵌套聚合

先按分類分組 → 再求每組的平均價格

GET /product/_search
{
  "size": 0,
  "aggs": {
    "group_by_category": {
      "terms": {
        "field": "category"
      },
      "aggs": {
        "avg_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}

結(jié)果

手機 → 平均價格 5800

電腦 → 平均價格 7200

按價格區(qū)間統(tǒng)計(range 聚合)

電商最常用:價格分段統(tǒng)計

GET /product/_search
{
  "size": 0,
  "aggs": {
    "price_range": {
      "range": {
        "field": "price",
        "ranges": [
          { "to": 3000 },
          { "from": 3000, "to": 6000 },
          { "from": 6000 }
        ]
      }
    }
  }
}

對搜索結(jié)果聚合。

例如,我想知道價格高于3000元的手機品牌有哪些

GET /items/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category": "手機"
          }
        },
        {
          "range": {
            "price": {
              "gte": 300000
            }
          }
        }
      ]
    }
  }, 
  "size": 0, 
  "aggs": {
    "brand_agg": {
      "terms": {
        "field": "brand",
        "size": 20
      }
    }
  }
}

求平均值(avg)

GET /product/_search
{
  "size": 0,
  "aggs": {
    "avg_price": {
      "avg": {
        "field": "price"
      }
    }
  }
}

求和(sum)

GET /product/_search
{
  "size": 0,
  "aggs": {
    "total_price": {
      "sum": {
        "field": "price"
      }
    }
  }
}

最大值、最小值(max /min)

GET /product/_search
{
  "size": 0,
  "aggs": {
    "max_price": {
      "max": {
        "field": "price"
      }
    },
    "min_price": {
      "min": {
        "field": "price"
      }
    }
  }
}

例:

統(tǒng)計價格高于3000的手機品牌,形成一個個桶。對桶內(nèi)的商品做運算,獲取每個品牌價格的最小值、最大值、平均值。

GET /items/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "category": "手機"
          }
        },
        {
          "range": {
            "price": {
              "gte": 300000
            }
          }
        }
      ]
    }
  }, 
  "size": 0, 
  "aggs": {
    "brand_agg": {
      "terms": {
        "field": "brand",
        "size": 20
      },
      "aggs": {
        "stats_meric": {
          "stats": {
            "field": "price"
          }
        }
      }
    }
  }
}

stat聚合,可以同時獲取min、max、avg的結(jié)果。

.RestClient實現(xiàn)聚合

可以看到在DSL中,aggs聚合條件與query條件是同一級別,都屬于查詢JSON參數(shù)。因此依然是利用request.source()方法來設(shè)置。

不過聚合條件的要利用AggregationBuilders這個工具類來構(gòu)造。DSL與JavaAPI的語法對比如下:

聚合結(jié)果與搜索文檔同一級別,因此需要單獨獲取和解析。具體解析語法如下:

@Test
void testAgg() throws IOException {
    // 1.創(chuàng)建Request
    SearchRequest request = new SearchRequest("items");
    // 2.準備請求參數(shù)
    BoolQueryBuilder bool = QueryBuilders.boolQuery()
            .filter(QueryBuilders.termQuery("category", "手機"))
            .filter(QueryBuilders.rangeQuery("price").gte(300000));
    request.source().query(bool).size(0);
    // 3.聚合參數(shù)
    request.source().aggregation(
            AggregationBuilders.terms("brand_agg").field("brand").size(5)
    );
    // 4.發(fā)送請求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 5.解析聚合結(jié)果
    Aggregations aggregations = response.getAggregations();
    // 5.1.獲取品牌聚合
    Terms brandTerms = aggregations.get("brand_agg");
    // 5.2.獲取聚合中的桶
    List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
    // 5.3.遍歷桶內(nèi)數(shù)據(jù)
    for (Terms.Bucket bucket : buckets) {
        // 5.4.獲取桶內(nèi)key
        String brand = bucket.getKeyAsString();
        System.out.print("brand = " + brand);
        long count = bucket.getDocCount();
        System.out.println("; count = " + count);
    }
}

到此這篇關(guān)于Elasticsearch安裝 + CRUD + 查詢實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Elasticsearch 入門到實戰(zhàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis批量更新報錯問題

    Mybatis批量更新報錯問題

    這篇文章主要介紹了Mybatis批量更新報錯的問題及解決辦法,包括mybatis批量更新的兩種方式,需要的的朋友參考下
    2017-01-01
  • java樹形菜單對象生成

    java樹形菜單對象生成

    這篇文章主要為大家詳細介紹了java樹形菜單對象生成,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • 利用靜態(tài)方法獲取spring的bean實例

    利用靜態(tài)方法獲取spring的bean實例

    文章介紹了如何在Spring框架中通過工具類的靜態(tài)方法獲取Spring命名空間中的bean,思路包括定義bean并實現(xiàn)ApplicationContextAware接口,然后在代碼中執(zhí)行特定代碼獲取bean,擴展部分詳細講解了加載原理和注意事項
    2025-11-11
  • 詳解spring boot實現(xiàn)多數(shù)據(jù)源代碼實戰(zhàn)

    詳解spring boot實現(xiàn)多數(shù)據(jù)源代碼實戰(zhàn)

    本篇文章主要介紹了詳解spring boot實現(xiàn)多數(shù)據(jù)源代碼實戰(zhàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • SpringBoot部署和前端連接問題解決的完整指南(net::ERR_CONNECTION_REFUSED)

    SpringBoot部署和前端連接問題解決的完整指南(net::ERR_CONNECTION_REFUSED)

    在開發(fā)和部署 Spring Boot 應用時,可能會遇到各種問題,例如 JAR 文件無法運行、前端無法連接后端服務等,本文將詳細總結(jié)這些問題的解決方法,幫助你順利部署和運行 Spring Boot 應用,需要的朋友可以參考下
    2025-01-01
  • Spring事務管理只對出現(xiàn)運行期異常進行回滾

    Spring事務管理只對出現(xiàn)運行期異常進行回滾

    Spring的事務管理默認只對出現(xiàn)運行期異常(java.lang.RuntimeException及其子類)進行回滾,需要了解更多Spring事務方面的知識,可詳看本文
    2012-11-11
  • springboot實現(xiàn)配置本地訪問端口及路徑

    springboot實現(xiàn)配置本地訪問端口及路徑

    這篇文章主要介紹了springboot實現(xiàn)配置本地訪問端口及路徑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Web Service 運行原理詳細介紹

    Web Service 運行原理詳細介紹

    這篇文章主要介紹了 Web Service 運行原理詳細介紹的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Java中Word與PDF轉(zhuǎn)換為圖片的方法詳解

    Java中Word與PDF轉(zhuǎn)換為圖片的方法詳解

    這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)將Word與PDF轉(zhuǎn)換為圖片,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-10-10
  • Java實現(xiàn)壓縮圖片大小

    Java實現(xiàn)壓縮圖片大小

    這篇文章主要為大家詳細介紹了Java實現(xiàn)壓縮圖片大小,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04

最新評論

南和县| 万州区| 肇源县| 娱乐| 牡丹江市| 神池县| 盐边县| 扎鲁特旗| 思茅市| 从江县| 门头沟区| 永丰县| 牟定县| 图片| 鄂托克前旗| 稻城县| 柯坪县| 阿瓦提县| 霍山县| 吉林市| 永泰县| 克东县| 辽宁省| 乐亭县| 乌什县| 和静县| 谷城县| 休宁县| 关岭| 平安县| 宜章县| 星子县| 巴林右旗| 喀什市| 金门县| 乌兰县| 奉新县| 库尔勒市| 当涂县| 札达县| 通化县|