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
