主頁 > 後端開發 > spring boot集成Elasticsearch-SpringBoot(25)

spring boot集成Elasticsearch-SpringBoot(25)

2022-08-17 09:32:39 後端開發

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" >
        <destination>localhost:9601</destination>
        <encoder charset="UTF-8" />
    </appender>
    <appender name="STDOUT" >
        <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"))
                            //在品牌聚合桶內進行嵌套聚合
                           );

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/501989.html

標籤:其他

上一篇:api進階Day2(低級流)檔案流的輸出流、讀取流。向檔案中寫入文本資料、讀取檔案中的字串、用lambda運算式創建檔案過濾器。

下一篇:IOS OpenGL ES GPUImage 排除混合 GPUImageExclusionBlendFilter

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more