spring boot集成Elasticsearch-SpringBoot(25)

来源:https://www.cnblogs.com/liwenruo/archive/2022/08/16/16586524.html
-Advertisement-
Play Games

1. Elasticsearch—搜索應用伺服器 1.1 什麼是搜索引擎 搜索引擎(search engine )通常意義上是指:根據特定策略,運用特定的爬蟲程式從互聯網上搜集信息,然後對信息進行處理後,為用戶提供檢索服務,將檢索到的相關信息展示給用戶的系統。 而我們講解的是捜索的索引和檢索,不涉及 ...


1. Elasticsearch—搜索應用伺服器

  1.1 什麼是搜索引擎

  搜索引擎(search engine )通常意義上是指:根據特定策略,運用特定的爬蟲程式從互聯網上搜集信息,然後對信息進行處理後,為用戶提供檢索服務,將檢索到的相關信息展示給用戶的系統。

  而我們講解的是捜索的索引和檢索,不涉及爬蟲程式的內容爬取。大部分公司的業務也不會有爬取工作,而只提供查詢服務,而且Elasticsearch也只是提供這方面的功能。

  1.2 認識 Elasticsearch

  Elasticsearch是一個分散式、RESTful風格的搜索和數據分析引撃。通過它,能夠執行及合併多種類型的搜索(結構化數據、非結構化數據、地理位置、指標),解決不新涌現出的各種需求。

  Elasticsearch使用的是標準的RESTful風格的API,使用JSON提供多種語言(Java、 Python、.Net、SQL和PHP)的支持,它可以快速地存儲、搜索和分析海量數據。

  Elasticsearch是用Java語言開發的,並使用Lucene作為其核心來實現所有索引和搜索的功能。它的目的是:通過簡單的RESTful API來隱藏Lucene的複雜性,從而讓全文搜索變得簡單。

  Elasticsearch是一個開源的高擴展的分散式全文檢索引擎,可以近乎實時地存儲、檢索數據; 本身擴展性很好,允許多台伺服器協同工作,每台伺服器可以運行多個實例。單個實例稱為一個節(node), 一組節點構成一個集群(cluster)。分片是底層的工作單元,文檔保存在分片內,分片又被分配到集群內的各個節點里,每個分片僅保存全部數據的一部分。

  當Elasticsearch的節點啟動後,它會使用多播(multicast)或單播(用戶更改了配置)尋找集群中的其他節點,並與之建立連接。

  1.3 Elasticsearch 應用案例

  • GitHub: 2013年年初,GitHub把Solr緩存改成了Elasticsearch,以便用戶搜索20TB 的數據,包括13億個文件和1300億行代碼。
  • 維基百科:啟動以Elasticsearch為基礎的核心搜索架構SoundCloud,為1.8億用戶提供即時而精準的音樂搜索服務。
  • 百度:百度使用Elasticsearch作為數據分析引擎,20多個業務稅採集伺服器上的各類數據及用戶自定義數據,通過對各種數據進行多維分析,輔助定位異常。其單集群最大100台機器,200個Elasticsearch節點,每天導入超過30TB的數據。

除這些公司外,Stack Overflow、新浪、阿裡、360、攜程、有贊、蘇寧都在使用它。它被廣泛地用於各大公司的站內搜索、IT系統搜索(OA、CRM、ERP)、數據分析等工作中。

 1.4 對比 Elasticsearch 與 MySQL

  儘管將Elasticsearch與MySQL進行對比並不科學,但是這樣的對比能區分Elasticsearch 和MySQL資料庫的區別,便於快速用熟悉的知識來理解Elasticsearch 。所以,本節採用對比的方式來講解Elasticsearch。Elasticsearch與MySQL的結構對比見表13-1。

  

  圖 13-1

  • 關係型資料庫中的資料庫,相當於Elasticsearch中的索引(index )。
  • 一個資料庫下麵有多張表(table),相當於一個索引(index)下麵有多個類型(type)。
  • 一個資料庫表(table)下的數據由多行(row)多列(column屬性)組成,相當於一個 type由多個文檔(document)和多個field組成。
  • 在關係型資料庫中,schema定義了表、每個表的欄位,還有表和欄位之間的關係;在 Elasticsearch中,mapping定義索引下的type的欄位處理規則,即索引如何建立、索引類型、 是否保存原始索引 JSON文檔、是否壓縮原始JSON文檔、是否需要分詞處理、如何進行分詞處理等。
  • 在 MySQL 資料庫中的增(insert )、刪(delete )、改(update )、查 ( select)操作相 當於 Elasticsearch 中的增(put/post )、刪(delete )、改(update )、查(get)

  客戶端主要通過"方法(PUT/POST/GET/ DELETE ) + http://ip:埠/索引名稱/類型/主鍵” 來訪問內容。

  1.5 認識 ElasticSearchRepository

  Spring-data-elasticsearch 是 Spring 提供的操作 Elasticsearch 的數據介面,它封裝了大量的基礎操作。通過它可以很方便地操作Elasticsearch的數據。

  通過繼承ElasticsearchRepository來完成基本的CRUD及分頁操作,和普通的 JPA沒有什 麽區別。比如下麵實體Product的Repository繼承ElasticsearchRepository後,可以在 Elasticsearch文檔中進行查找和比較等操作。具體使用方法見以下代碼:

@Component
public interface UserRepository extends ElasticsearchRepository<User,Long> {
    Optional<User> findById(Long id);
    User findByUsername(String username);
    List<User> findByEmail(String email);
}

  ElasticsearchRepository有幾個特有的search方法,用來構建一些Elasticsearch查詢, 主要由QueryBuilder和SearchQuery兩個參數來完成一些特殊查詢。

  實現類NativeSearchQuery實現了 QueryBuilder和SearchQuery方法,要構建複雜查詢, 可以通過構建NativeSearchQuery類來實現。

  —般情況下,不是直接新建NativeSearchQuery類,而是使用NativeSearchQueryBuilder 來完成NativeSearchQuery的構建。具體用法見以下代碼:

NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery()
    .withFilter()
    .withSort()
    .withXXX().build();

  1.6 認識 ElasticsearchTemplate

  

  ElasticsearchTemplate是Spring對Elasticsearch的API進行的封裝,主要用來對索引進行創建、刪除等操作。它繼承了 ElasticsearchOperations 和 ApplicationContextAware 介面。 ElasticSearchTemplate 提供一些比 ElasticsearchRepository 更底層的方法。

  ElasticsearchOperations介面中常用的方法如下。

    • createlndex()方法:創建索引,返回值為布爾類型數據。
    • indexExists()方法:查詢索引是否存在,返回值為布爾類型數據。
    • putMapping()方法:  創建映射,返回值為布爾類型數據。
    • getMapping()方法:得到映射,返回值為一個Map數據。
    • deletelndex()方法:刪除索引,返回值為布爾類型數據。

  1.7 認識註解@Document

  註解@Document作用於類,用於標記實體類為文檔對象。

  存儲在Elasticsearch中的一條數據,即是一個文檔,類似關係型資料庫的一行數據。 Elasticsearch會索引每個文檔的內容,以便搜索。它使用JSON格式,將數據存儲到Elasticsearch 中,實際上是將JSON格式的字元串發送給了 Elasticsearch。

  1.document的核心元數據

  document有三個核心元數據,分別是 _index、_type、_id

  (1)_index。代表一個document存放在哪個index中,類似的數據放在一個索引中,非類似的數據放在不同的索引中。index中包含了很多類似的document,這些document的field很大一 部分是相同的。索引名稱必須小寫,不能用下畫線開頭,不包含逗號。

  (2)_type。代表document屬於index的哪個類別,一個索引通常會劃分為多個type,邏輯 index不同的數據進行分類。type名稱可以是大寫或小寫,但是不能用下畫線開頭,不能包含逗號。

  (3)_id。代表document的唯一標識,與_index和_type —起可以標識和定位一個 document。預設自動創建id,也可以手動指定document的id。

 2.document id的手動指定和自動生成

  (1)手動指定 document id

  如果需要從某些其他系統中導入一些數據到Elasticsearch,則會採用手動指定id的形式,因 為一般情況下系統中已有數據的唯一標識,可以用作Elasticsearch中的document的id。

  其語法格式為:

put /index/type/id
{
    "json"
}

  (2)自動生成 document id

  其語法格式為:

post /index/type
{
    "json"
}

  自動生成的id長度為20個字元,URL安全、Base64編碼、GUID、分散式系統並行生成時不會發生衝突。

  3. document的_source元數據,以及定製返回結果

  _source元數據是在創建document時放在body中的JSON數據。在預設情況下,查找數據時會返回全部數據。如果要定製返回結果,則可以指定_source中返回哪些field

  例如:

  GET /_index/_type/1?_source=field

  1.8 管理索引

    1. 創建索引

      (1)根據類的信息自動生成創建索引

        下麵代碼是根據實體類創建一個名為 "ec" 的索引,並定義type是“product”。由於是單機環境,所以定義副本為0,分片為預設值5。

@Data
@Document(indexName = "user",type = "user",replicas = 0,shards = 5)
public class User implements Serializable {
    private int id;
    private String username;
    private String password;
}

代碼解釋如下。

  • indexName :對應索引庫名稱,可以理解為資料庫名。必須小寫,否則會報 "org.elasticsearch.indices.InvalidlndexNameException"異常。
  • type:對應在索引庫中的類型,可以將其理解為“表名”
  • shards:分片數量,預設值為5。
  • replicas:副本數量,預設值為1。如果是單機環境,則健康狀態為“yellow”。如果要成為 "green”,則指定值為0即可。

      (2)手動創建索引

 可以使用createindex方法手動指定indexName和Settings,再進行映射。在使用前,要先註入ElasticsearchTemplate,使用方法如下。

  • 根據索引名創建索引:
elasticsearchTemplate.createIndex("indexname");
  • 根據類名創建索引:
elasticsearchTemplate.createIndex(User.class);

    2. 查詢索引

  • 根據索引名查詢:
elasticsearchTemplate.indexExists("indexname");
  • 根據類名查詢:
elasticsearchTemplate.indexExists(User.class);

    3. 刪除索引

    可以根據索引名和類名對索引進行刪除。

  • 根據索引名刪除:
elasticsearchTemplate.deleteIndex("indexname");
  • 根據類名刪除:
elasticsearchTemplate.deleteIndex(User.class);

2. 用ELK管理Spring Boot應用程式的日誌  

ELK 是 Elasticsearch+Logstash+Kibana 的簡稱。

Logstash負責將數據信息從輸入端傳輸到輸出端,比如將信息從MySQL傳入Elasticsearch, 還可以根據自己的需求在中間加上濾網。Logstash提供了很多功能強大的濾網,以滿足各種應用場景。

Logstash有以下兩種工作方式。

  • 每一臺機器啟動一個Logstash服務,讀取本地的數據文件,生成流傳給Elasticsearch。
  • Logback引入Logstash包,然後直接生產JSON流,傳給一個中心的Logstash伺服器,Logstash伺服器再傳給Elasticsearch,最後,Elasticsearch將其流傳給Kibana。

Kibana是一個開源的分析與可視化平臺,和Elasticsearch —起使用。可以用Kibana搜索、 查看、交互存放在Elasticsearch索引里的數據。使用各種不同的圖標、表格、地圖等,Kibana能夠很輕昜地展示高級數據分析與可視化。

ELK架構為數據分散式存儲、日誌解析和可視化創建了一個功能強大的管理鏈。三者相互配合, 取長補短,共同完成分散式大數據處理工作。

  2.1 安裝 Elasticsearch

  (1)通過官網下載Elasticsearch。

  (2)在下載完成後,首先將其解壓到合適的目錄,然後進入解壓目錄下的bin目錄,雙擊 bat文件啟動Elasticsearch。這裡需要確保全裝的Java版本在1.8及以上。

   (3)訪問“http://localhost:9200/”,當看到返回一串JSON格式的代碼時,則說明已經安裝成功了。

  根據應用需要,還可以安裝Elasticsearch必要的一些插件,如Head、kibana、IK (中文分 詞)、graph。

  2.2 安裝 Logstash

  1. 安裝 Logstash

  (1)訪問 Elasticsearch 官網下載 Logstash

    (2)將下載文件解壓到自定義的目錄即可。

  2. 配置 Logstash

  (1 )在解壓文件的config目錄下新建log4j_to_es.conf文件,寫入以下代碼:

input {
	beats {
		port => 5044
		codec => "json"
	}
}

output {
	elasticsearch {
		hosts => "127.0.0.1:9200"
		codec => json
	}
}

  這裡一定要註意:這是UTF-8的格式,不要帯BOM。如果啟動時岀現錯誤,則可以用“logstash -f ../config/xxx.conf -t“命令檢查配置文件是否錯誤。

  (2)新建文件 run.bat。寫入代碼 logstash -f .\config\log4j_to_es.conf保存。然後雙擊該配置文件,啟動Logstash。

    (3)訪問 localhost:9600 如出現以下內容,則代表配置成功。

{"host":"DESKTOP-0VSQ1JE","version":"8.3.3","http_address":"127.0.0.1:9600",
 "id":"f9a14845-005b-42f2-8725-9b3f67dafe86","name":"DESKTOP-0VSQ1JE",
 "ephemeral_id":"9ffa0b64-c9bb-4385-8924-6565b4cd8167","status":"green",
 "snapshot":false,"pipeline":{"workers":8,"batch_size":125,"batch_delay":50},
 "build_date":"2022-07-23T19:31:54Z","build_sha":"0205f0c5f2ff21118c161e769e8f2bbb79ee81a3",
 "build_snapshot":false}

  2.3 安裝Kibana

Kibana是官方推出的Elasticsearch數據可視化工具。

  (1)通過訪問Elasticsearch官網下載Kibana。

  (2)解壓下載的壓縮文件,進入解壓目錄,雙擊Kibana目錄的bin/kibana.bat,以啟動 Kibana,當岀現以下提示時,代表啟動成功。

  [2022-08-16T16:30:45.443+08:00][INFO ][status] Kibana is now available (was degraded)

  (3)訪問localhost:5601就可以逬入Kibana控制台。

  單擊控制台左邊導航欄的“Dev-tools”按鈕,可以進入Dev-tools界面。單擊"Get to work", 然後在控制台輸入“GET/_cat/health?”命令,可以查看伺服器狀態。如果在右側返回的結果中看到green或yellow ,則表示伺服器狀態正常。

  2.4 配置 Spring Boot 項目

  (1)添加項目依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j</artifactId>
    <version>1.3.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.2</version>
</dependency>

  (2)添加配置文件logback.xml,這裡在Spring Boot項目里添加一個配置又件,見以下代碼:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>localhost:9601</destination>
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="UTF-8">
            <pattern>%d{HH:mm:ss.SSS}[%thread]%-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="LOGSTASH"/>
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

  2.5 創建日誌計劃任務

  在Spring Boot項目中創建logTest類,用於測試將日誌通過Logstash發送到Elasticsearch, 見以下代碼:

3. Spring Boot集成Elasticsearch

  實現增加、刪除、修改、查詢文檔的功能

  3.1 集成 Elasticsearch

Spring Boot 提供了 Starter ( spring-boot-starter-data-elasticsearch )來集成 Elasticsearch

  • 優點:開發速度快,不要求熟悉Elasticsearch的一些API,能快速上手。即使之前對 Elasticsearch不瞭解,也能通過方法名或SQL語句快速寫岀自己需要的邏輯。而具體轉換成API層的操作則是由框架底層實現的。
  • 缺點:使用的Spring Boot的版本Elasticsearch的版本也有了要求,不能超過某些版本號,在部署時需要註意。如果採用API方式,則能解決這個問題。

  (1)添加依賴

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
</dependency>

  (2)添加application.yml配置

spring:
  data:
    elasticsearch:
      repositories:
        enabled: true #是否開啟本地存儲
      cluster-nodes: 127.0.0.1:9200
      cluster-name: elasticsearch

  3.2 創建實體

  (1)創建實體

  這裡根據類的信息自動生成,也可以手動指定索引名稱。ElasticsearchTemplate中提供了創建素引的API,因為進行本機測試,沒做集群,所以replicas副本先設置為0。見以下代碼:

package com.intehel.demo.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;

@Document(indexName = "ec",replicas = 0,shards = 5,type = "product")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product implements Serializable {
    //@Id註解必須是org.springframework.data.annotation.Id;
    @Id
    private Long id;
    //ik_max_word使用ik分詞器
    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String name;
    //在存儲數據時,不會對category進行分詞
    @Field(type = FieldType.Keyword)
    private String category;
    //價格
    @Field(type = FieldType.Double)
    private Double price;
    //index = false 表示不建立索引
    @Field(index = false,type = FieldType.Keyword)
    private String images;
    private String body;
}

代碼解釋如下,

  • @ld註解:作用於成員變數,標記一個欄位作為id主鍵。
  • @Field註解:作用於成員變數,標記為文檔的欄位,需要指定欄位映射屬性type。
  • index:是否索引,布爾類型,預設為true。
  • store:是否存儲,布爾類型,預設為false,
  • analyzer;分詞器名稱,這裡的ik_max_word即使用IK分詞器。

  (2)創建數據操作介面

package com.intehel.demo.repository;

import com.intehel.demo.domain.Product;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.Optional;

public interface ProductRepository extends ElasticsearchRepository<Product,Long> {
    @Override
    Optional<Product> findById(Long id);
    Product findByName(String name);
}

  3.3 實現增加、刪除、修改和查詢文檔的功能

  在測試類中,實Elasticsearch文檔進行增加、刪除、修改和查詢的功能,見以下代碼:

查看代碼
 package com.intehel.demo;

import com.intehel.demo.domain.Product;
import com.intehel.demo.domain.User;
import com.intehel.demo.repository.ProductRepository;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Optional;

@SpringBootTest
@RunWith(SpringRunner.class)
class ElasticApplicationTests {
    private Integer PAGESIZE = 10;
    @Autowired
    private ProductRepository productRepository;
    @Test
    public void save(){
        long id = System.currentTimeMillis();
        Product product = new Product(id,"紅富士","水果",7.99,"jpg","測試");
        try {
            productRepository.save(product);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(product.getId());
    }
    @Test
    public void getProduct(){
        Product product = productRepository.findByName("紅富士");
        System.out.println(product.getId());
    }
    @Test
    public void updateProduct(){
        long id = 1660653233939L;
        Product product = new Product(id,"烤冷面","小吃",7.00,"jpg","測試");
        productRepository.save(product);
    }
    @Test
    public void getProductById(){
        Optional<Product> product = productRepository.findById(1660653233939L);
        System.out.println(product.get().getName()+product.get().getBody());
    }
    @Test
    public void deleteProduct(){
        long id = 1660653233939L;
        productRepository.deleteById(id);
    }
    @Test
    public void getAll(){
        Iterable<Product> list = productRepository.findAll(Sort.by("id").ascending());
        for (Product product : list) {
            System.out.println(product);
        }
    }
}

4. Elasticsearch查詢

  4.1 自定義方法

   可以根據Spring Data提供的方法名稱,實現自己想自定義的查詢功能:無須寫實現類,只要繼承ElasticsearchRepository介面即可。如"findByTitle"表示根據"title”進行查詢,具體方法見表13~2

  

圖 13-2

  如果要查詢價格在7 ~ 8元的商品,則可以在介面類加上"List<Product> findByPriceBetween(Double min, Double max);"方法,見以下代碼:

public interface ProductRepository extends ElasticsearchRepository<Product,Long> {
    @Override
    List<Product> findByPriceBetween(Double min, Double max);
}

  然後,在測試類中直接使用自定義的"findByPriceBetween"方法查詢出數據,見以下代碼:

@Test
public void queryByPriceBetween(){
    Iterable<Product> list = productRepository.findByPriceBetween(7.00,8.00);
    for (Product product : list) {
        System.out.println(product);
    }
}

  4.2 精準查詢

  1.單參數 termQuery

  用法見以下代碼:

QueueBuilder queueBuilder = QueueBuilder.termQuery("欄位名","查詢值");

它是不分詞查詢。因為不分詞,所以漢字只能查詢一個字,而多字母的英語單詞算一個字

具體實現見以下代碼:

@Test
public void queryByPriceBetween(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("name","富"));
    //查詢詞,只能查詢一個漢字,或一個英文單詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  2.多參數--termsQuery

  terms可以提供n個查詢的參數對一個欄位進行查詢,用法見以下代碼。註意,這裡是term的複數形式terms

  QueueBuilder queueBuilder = QueueBuilder.termsQuery("欄位名","查詢值","查詢值");

@Test
public void queryByPriceBetween(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.termsQuery("name","富","帥"));
    //查詢詞,只能查詢一個漢字,或一個英文單詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }

}

  3.分詞查詢-- matchQuery

  分詞查詢採用預設的分詞器.用法見以下代碼

  QueueBuilder queueBuilder = QueueBuilder.matchQuery("欄位名","查詢值");

  具體實現見以下代碼:

@Test
public void matchQuery() throws Exception {}{
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("name","紅士"));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  4.多欄位查詢 multiMatchQuery

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.multiMatchQuery("紅富士Gila","name","body"));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  4.3 模糊查詢

  常見的模糊查詢的方法有4種

  1.左右模糊

QueryBuilders.queryStringQuery("查詢值").field("欄位名")

   具體實現見以下代碼:

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.queryStringQuery("我覺得紅富士好吃").field("name"));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  2. 首碼查詢--- prefixQuery

  如果欄位沒分詞,則匹配整個欄位首碼,用法見以下代碼:

QueryBuilders.prefixQuery("欄位名","查詢值")

  具體實現見以下代碼:

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.prefixQuery("name","士"));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

   3. 通配符查詢  wildcard query

  使用通配符方式進行查詢,支持通配符”*“和”?“,”*“代表任意字元串,”? ”代表任意一個字元。

  (1)使用通配符”*“

  通配符可以匹配多個值,用法見以下代碼:

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.wildcardQuery("name","*士"));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  (2)使用通配符“?”

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.wildcardQuery("name","紅富?"));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  4. 分詞模糊査詢   fuzzy query

  分詞模糊查詢即匹配截取字元串為字前或後加1個詞的文檔,這裡通過增加fuzziness (模糊) 屬性來查詢,fuzziness的含義是檢索的term前後增加或減少n個詞的匹配查詢。用法見以下代碼

QueryBuilders.fuzzyQuery("欄位名","查詢值").fuzziness(Fuzziness.ONE)

  具體實現見以下代碼:

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.fuzzyQuery("name","士").fuzziness(Fuzziness.ONE));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  5. 相似內容推薦

  相似內容的推薦是給定一篇文檔信息,然後向用戶推薦與該文檔相似的文檔。通過 Elasticsearch的More like this查詢介面,可以非常方便地實現基於內容的推薦,用法見以下代碼: QueryBuilders.moreLikeThisQuery(new StnngQ ("WfiS"}).addLikeText("@i®ffi");

  如果不指定欄位名,則預設全部,常用在相似內容的推薦上。

  QueryBuilders.moreLikeThisQuery(new String[]{"欄位名"}).addLikeText("查詢值")

  4.4 範圍查詢

  閉區間查詢:QueryBuilders.rangeQuery("欄位名").from("值1").to("值2")

  開區間查詢:QueryBuilders.rangeQuery("欄位名").from("值1").to("值2").includeLower(false).includeUpper(false)

  大於:QueryBuilders.rangeQuery("欄位名").gt("查詢值")

  大於或等於:QueryBuilders.rangeQuery("欄位名").gte("查詢值")

  小於:QueryBuilders.rangeQuery("欄位名").lt("查詢值")

  小於或等於:QueryBuilders.rangeQuery("欄位名").lte("查詢值")

  4.5 組合查詢

組合查詢是可以設置多個條件的查詢方式,用來組合多個查詢。有4種方式。

  • must:代表文檔必須完全匹配條件,相當於and,會參與計算分值。
  • mustnot:代表必須不滿足匹配條件。
  • filter:代表返回的文檔必須滿足filter條件,但不會參與計算分值。
  • should:代表返回的文檔可能滿足條件,也可能不滿足條件,有多個should時滿足任何一 個就可以,相當於or,可以通過minimum_should_match設置至少滿足幾個。

  4.6 分頁查詢

  使用NativeSearchQueryBuilder實現分頁查詢,用法見以下代碼:

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("name","富"));
    nativeSearchQueryBuilder.withPageable(PageRequest.of(0,5));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  如果要進行排序,只要在分頁查詢上構建withSort參數即可,用法見以下代碼:

@Test
public void matchQuery(){
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("name","富"));
    nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC));
    nativeSearchQueryBuilder.withPageable(PageRequest.of(0,5));
    //查詢詞
    Page<Product> page = productRepository.search(nativeSearchQueryBuilder.build());
    //搜索,獲取結果
    for (Product product : page){
        System.out.println(product);
    }
}

  4.7 聚合查詢

  聚合(aggregation )是Elasticsearch的一個強大功能,可以極其方便地實現對數據的統計、分析工作。搜索是查找某些具體的文檔,聚合就是對這些搜索到的文檔進行統計,可以聚合出更加細緻的數據。它有兩個重要概念。

  • Bucket (桶/集合):滿足特定條件的文檔的集合,即分組。
  • Metric (指標/度量):對桶內的文檔進行統計計算(最小值、最大值),簡單理解就是進行運算

聚合由AggregationBuilders類來構建,它提供的靜態方法見表13-3

  

表 13-3

  具體用法見以下代碼:

public List<StringTerms.Bucket> searchBybucket(){
    NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
    queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""},null));
    //指定索引的類型,只先從各分片中查詢匹配的文檔,再重新排名,取前size個文檔
    queryBuilder.withSearchType(SearchType.QUERY_THEN_FETCH);
    //添加一個新的聚合,聚合類型為terms,聚合名稱為brands,聚合欄位為brand
    queryBuilder.addAggregation(AggregationBuilders.terms("brand").field("brand"));
    //查詢,需要把結果強轉為Aggregatedpage類型,Aggregatedpage:聚合查詢的結果類,它是Page<T>的子介面
    AggregatedPage<Product> productsPage = (AggregatedPage<Product>) productRepository.search(queryBuilder.build());
    //從結果中取出名為brands的聚合解析
    //強轉為StringTerm類型
    StringTerms aggregations = (StringTerms) productsPage.getAggregation("brands");
    //獲取桶
    List<StringTerms.Bucket> buckets = aggregations.getBuckets();
    //遍歷
    for (StringTerms.Bucket bucket : buckets) {
        //獲取桶中的key
        System.out.println(bucket.getKey());
        //獲取桶中的文檔數量
        System.out.println(bucket.getDocCount());
    }
    return buckets;
}

  還可以嵌套聚合,在聚合AggregationBuilders中使用subAggregation,用法見以下代碼:

queryBuilder.addAggregation(AggregationBuilders.terms("brand").field("brand")
                            .subAggregation(AggregationBuilders.avg("price_avg").field("price"))
                            //在品牌聚合桶內進行嵌套聚合
                           );

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在React中上下文是一種通信方案。 上下文的特點 在組件樹中,是一種自上而下的單向數據流通信方案,數據只能從父組件註入,在子組件中訪問。 組件關係只要滿足“父組件-後代組件”這種關係時,都可以使用上下文通信。 在父組件中provide提供數據,在後代組件中註入並使用,這種通信不具有響應式,有點像v ...
  • 使用three.js(webgl)搭建智慧樓宇、設備檢測、數字孿生、物聯網3D、物業3D監控、物業基礎設施可視化運維、3D定位、三維室內定位、3d建築,3d消防,消防演習模擬,3d庫房,webGL,threejs,3d機房,bim管理系統 ...
  • HTTP 起源 HTTP 是由蒂姆·伯納斯-李(TimBerners—Lee)於1989年在歐洲核子研究組織(CERN)所發起 其中最著名的是 1999 年 6 月公佈的 RFC 2616,定義了 HTTP 協議中現今廣泛使用的一個版本——HTTP 1.1 HTTP 是什麼 全稱:超文本傳輸協議(H ...
  • 本文將探討一下,在多行文本情形下的一些有意思的文字動效。 多行文本,相對於單行文本,場景會複雜一些,但是在實際業務中,多行文本也是非常之多的,但是其效果處理比起單行文本會更困難。 單行與多行文本的漸隱 首先,我們來看這樣一個例子,我們要實現這樣一個單行文本的漸隱: 使用 mask,可以輕鬆實現這樣的 ...
  • 結構型模式所描述的是如何將類和對象結合在一起來形成一個更大的結構,它描述兩種不同的事物:類和對象,根據這一點,可分為類結構型和對象結構型模式。類結構型模式關心類的組合,由多個類可以組合成一個更大的系統,在類結構型模式中一般只存在繼承關係和實現關係;對象結構型模式關心類與對象的組合,通過關聯關係使得在... ...
  • 創建型模式是處理對象創建的設計模式,試圖根據實際情況使用合適的方式創建對象。基本的對象創建方式可能會導致設計上的問題,或增加設計的複雜度。創建型模式通過以某種方式控制對象的創建來解決問題。創建型模式由兩個主導思想構成。一是將系統使用的具體類封裝起來,二是隱藏這些具體類的實例創建和結合的方式。 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 1.註冊功能 具體的效果圖如下: 註冊功能涉及到的邏輯步驟: 1.搭建前端html頁面 2.向後端提交用戶輸入數據 3.對用戶輸入的數據格式進行校驗 4.頁面輸入數據格式錯誤,及時向用戶進行提示/正確則保存到資料庫 所以,提到校驗和提交數據,這就需要我們用到forms組件!! 回顧一下forms組件 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...