該怎么學(xué)elasticsearch?看這篇就夠啦~
來(lái)源 | Java技術(shù)迷(ID:JavaFans1024)
安裝ElasticSearch
首先來(lái)到官網(wǎng)下載ElasticSearch:https://www.elastic.co/cn/elasticsearch/
'
點(diǎn)擊按鈕進(jìn)行下載:

我們以Windows版本為例,下載完成后解壓出來(lái),然后執(zhí)行bin目錄下的 elasticsearch.bat 文件:

等待啟動(dòng)完成后,訪問(wèn)http://localhost:9200/:

看到此界面則說(shuō)明ElasticSearch啟動(dòng)成功了。
相關(guān)概念
在正式學(xué)習(xí)ElasticSearch之前,我們先來(lái)了解一下ElasticSearch。
Elasticsearch是一個(gè)基于Lucene的搜索服務(wù)器。它提供了一個(gè)分布式多用戶能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java語(yǔ)言開(kāi)發(fā)的,并作為Apache許可條款下的開(kāi)放源碼發(fā)布,是一種流行的企業(yè)級(jí)搜索引擎。
在ElasticSearch中有四個(gè)相關(guān)的概念:
索引 類型 文檔 字段
我們可以將其類比到關(guān)系型數(shù)據(jù)庫(kù)中,索引就是一個(gè)數(shù)據(jù)庫(kù),類型就是一張數(shù)據(jù)表,而文檔就是數(shù)據(jù)表中的一行,字段就是數(shù)據(jù)表中的一列,如下圖:

ElasticSearch通常用于網(wǎng)站的全文檢索,這意味著ElasticSearch將承擔(dān)著整個(gè)系統(tǒng)最大搜索量的搜索業(yè)務(wù),想象一下在淘寶搜索入口上搜索一個(gè)手機(jī),系統(tǒng)背后需要經(jīng)歷多么大的數(shù)據(jù)量查詢。然而在如此大數(shù)據(jù)量的情況下,ElasticSearch仍然能夠非常出色的完成任務(wù),它是如何做到的呢?
我們先來(lái)看一張關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)表:
+----+------------+
| id | name |
+----+------------+
| 1 | zhang san |
| 2 | zhang san2 |
| 3 | zhang san3 |
| 4 | li si |
+----+------------+
假設(shè)這張數(shù)據(jù)表的數(shù)據(jù)量非常龐大,若是想進(jìn)行模糊查詢,查詢姓 zhang 的用戶信息,那么它的效率一定是很低的,因?yàn)樗枰獜牡谝粭l數(shù)據(jù)開(kāi)始遍歷到最后一條數(shù)據(jù)。來(lái)看看ElasticSearch是如何做的,它采用的是一種叫 倒排索引 的方式,即:在插入數(shù)據(jù)的時(shí)候就建立了一張關(guān)鍵字與id的對(duì)應(yīng)表:
+---------+-------+
| keyword | id |
+----+------------+
| zhang | 1,2,3 |
| san | 1,2,3 |
| li | 4 |
| si | 4 |
+---------+-------+
它會(huì)將名字中的關(guān)鍵字提取出來(lái),并記錄當(dāng)前id擁有哪些關(guān)鍵字,將其存放起來(lái),此時(shí)我們查詢姓 zhang 的用戶信息時(shí),我們將直接得到姓 zhang 的用戶id為 1、2、3 ,然后通過(guò)id找到用戶信息即可,查詢效率大幅提升了。
需要注意的是,從ElasticSearch7.X版本開(kāi)始,Type的概念已經(jīng)被移除了。
索引
接下來(lái)我們就來(lái)看看ElasticSearch中索引的具體操作,因?yàn)樗腔赗ESTful web接口的,所以我們使用Postman進(jìn)行測(cè)試。
創(chuàng)建索引

訪問(wèn)路徑為 http://localhost:9200/user,請(qǐng)求方式一定要選擇PUT,了解RESTful接口的同學(xué)都知道,接口的請(qǐng)求方式?jīng)Q定了這次請(qǐng)求的行為,當(dāng)出現(xiàn)底部的響應(yīng)內(nèi)容時(shí),說(shuō)明索引創(chuàng)建成功了。
查詢索引
查詢索引非常簡(jiǎn)單,我們只需要修改剛才的請(qǐng)求方式為GET即可:

響應(yīng)的內(nèi)容是剛剛創(chuàng)建的索引信息,若是想查詢ElasticSearch中的所有索引,則訪問(wèn) _cat :

刪除索引
相信你已經(jīng)知道該如何刪除索引了吧,沒(méi)錯(cuò),只需要將請(qǐng)求方式修改為DELETE即可:

文檔
我們?cè)賮?lái)看看文檔的相關(guān)操作,文檔對(duì)應(yīng)關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)行。
創(chuàng)建文檔
創(chuàng)建文檔的方式也非常簡(jiǎn)單:

首先在訪問(wèn)路徑上添加 /_doc ,其次修改請(qǐng)求方式為POST,最后不要忘記添加請(qǐng)求體參數(shù),它將作為我們的文檔數(shù)據(jù)。需要注意的是,創(chuàng)建索引使用的是PUT請(qǐng)求,而創(chuàng)建文檔使用的是POST請(qǐng)求,千萬(wàn)不能搞混了,實(shí)在記不清的話,你可以這樣理解,當(dāng)我們?cè)趧?chuàng)建文檔時(shí),響應(yīng)內(nèi)容中有一項(xiàng) _id 參數(shù),而每次請(qǐng)求這個(gè) _id 都是會(huì)變化的,這就說(shuō)明該接口是不符合冪等性的。
冪等性就是指用戶對(duì)于同一操作發(fā)起的一次請(qǐng)求或者多次請(qǐng)求的結(jié)果是一致的,不會(huì)因?yàn)槎啻吸c(diǎn)擊而產(chǎn)生了副作用。
而PUT方式要求接口必須符合冪等性,所以我們?cè)趧?chuàng)建文檔時(shí)就不能選擇使用PUT方式,這樣記憶是不是會(huì)更好呢。
在創(chuàng)建文檔時(shí)我們可以通過(guò)url指定文檔的id:

因?yàn)榇藭r(shí)的id是由你自己指定的,所以每次發(fā)送請(qǐng)求得到的響應(yīng)結(jié)果其實(shí)是一樣的,符合冪等性,因此,這種指定id創(chuàng)建文檔的方式也可以使用PUT請(qǐng)求:

查詢文檔
通過(guò)GET請(qǐng)求方式即可查詢文檔:

使用 _search 即可查詢所有ElasticSearch中的所有文檔數(shù)據(jù):

更新文檔
更新文檔分為兩種方式:
全量更新 局部更新
其中全量更新指的是將文檔中的數(shù)據(jù)全部進(jìn)行更新,由于是全部更新,每次請(qǐng)求響應(yīng)的內(nèi)容是一致的,符合冪等性,所以可以使用PUT請(qǐng)求(當(dāng)然了,POST請(qǐng)求一定也是可以的):

而對(duì)于局部更新,因?yàn)槊看胃碌膬?nèi)容可能不同,導(dǎo)致響應(yīng)的結(jié)果也不同,它就不符合接口的冪等性,所以它只能使用POST請(qǐng)求進(jìn)行更新:

此時(shí)我們的url需要進(jìn)行修改,使用 _update 來(lái)指定此次操作為更新操作(對(duì)應(yīng)的還有 _create 操作,只不過(guò)它與 _doc 功能相同,都是創(chuàng)建索引),而且請(qǐng)求體參數(shù)也發(fā)生了變化,需要更新的屬性值需要寫在 doc 屬性中。
刪除文檔
只需將請(qǐng)求方式設(shè)置為DELETE即可完成對(duì)文檔的刪除:

高級(jí)查詢
作為全文檢索工具,ElasticSearch在查詢方面具有無(wú)與倫比的效率,為此,我們?cè)賮?lái)看看ElasticSearch中關(guān)于查詢的一些高級(jí)內(nèi)容。
條件查詢
要想實(shí)現(xiàn)條件查詢,我們就需要將查詢條件拼接到url中:

我們知道, _search 可以查詢ElasticSearch中的所有文檔數(shù)據(jù),通過(guò) q 參數(shù)即可傳入查詢條件。
使用url傳遞參數(shù)有諸多弊端,編寫麻煩而且容易出現(xiàn)亂碼問(wèn)題,所以我們可以將查詢條件作為請(qǐng)求體參數(shù)進(jìn)行傳遞:

請(qǐng)求體參數(shù)中, query 表示這是一個(gè)查詢條件, match 指定的是查詢模式,為匹配查詢,匹配內(nèi)容為 name 等于 zhangsan 。
ElasticSearch當(dāng)然也支持分頁(yè)查詢:

其中 from 用于指定頁(yè)碼, size 指定每頁(yè)記錄數(shù),這里則表示按每頁(yè)兩條記錄數(shù)進(jìn)行分頁(yè),并返回第一頁(yè)的文檔數(shù)據(jù)。請(qǐng)求參數(shù)中指定 _source 能夠指定響應(yīng)內(nèi)容中文檔的數(shù)據(jù),比如:
{
"query":{
"match":{
"name":"zhangsan"
}
},
"from":0,
"size":2,
"_source":["name"]
}
它表示在分頁(yè)查詢的基礎(chǔ)上只顯示 name 屬性值。若是想實(shí)現(xiàn)查詢時(shí)排序,則只需在請(qǐng)求體參數(shù)中添加一個(gè) sort 屬性:
{
"query":{
"match":{
"name":"zhangsan"
}
},
"from":0,
"size":2,
"_source":["name"],
"sort":{
"age":{
"order":"asc"
}
}
}
它表示按照年齡進(jìn)行升序。
多條件查詢
若是想實(shí)現(xiàn)多條件查詢,則需要進(jìn)一步封裝請(qǐng)求體參數(shù),比如查詢 name 為 zhangsan 且 age 等于 20 的用戶信息:

請(qǐng)求體參數(shù)為:
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"zhangsan"
}
},
{
"match":{
"age":"20"
}
}
]
}
}
}
其中 query 表示查詢,不必多說(shuō), bool 表示查詢條件,之后就是 must 了,它表示must中的內(nèi)容一定要成立,must中可以填寫多個(gè)查詢條件,match 表示匹配,匹配內(nèi)容為 name 等于 zhangsan , age 等于 20 。
若是想實(shí)現(xiàn)查詢 name 為 zhangsan 或者 lisi 的用戶,則需要將 must 替換為 should :
{
"query":{
"bool":{
"should":[
{
"match":{
"name":"zhangsan"
}
},
{
"match":{
"name":"lisi"
}
}
]
}
}
}
若是想查詢年齡在20~30之間的用戶信息,則我們需要借助 filter 屬性:
{
"query":{
"bool":{
"filter":{
"range":{
"age":{
"gt":20,
"lt":30
}
}
}
}
}
}
全文檢索

當(dāng)我們?cè)跈z索某個(gè)關(guān)鍵字的時(shí)候,ElasticSearch仍然能夠準(zhǔn)備查詢到相關(guān)信息,這是因?yàn)镋lasticSearch會(huì)將文字分詞并與文檔id作對(duì)應(yīng)形成倒排索引,相關(guān)內(nèi)容我們?cè)谇懊婢鸵呀?jīng)接觸到了,這就是ElasticSearch的全文檢索功能。當(dāng)我們的姓名是兩個(gè)漢字時(shí):
{
"query":{
"match":{
"name":"張李"
}
}
}
ElasticSearch仍然會(huì)將其分為 張 和 李 兩個(gè)字,并分別做匹配,若是我們就想查詢名字叫 張李 的用戶,那么就不能使用 match 匹配了,而是使用 match_phrase :
{
"query":{
"match_phrase":{
"name":"張李"
}
}
}
它表示的是完全匹配,即:匹配的內(nèi)容必須和屬性值完全一致。我們還可以讓匹配的內(nèi)容高亮顯示:
{
"query":{
"match_phrase":{
"name":"張三"
}
},
"highlight":{
"fields":{
"name":{}
}
}
}
使用 highlight 指定需要高亮顯示的屬性。
聚合查詢
若是想對(duì)查詢的數(shù)據(jù)進(jìn)行分組管理,在ElasticSearch中稱為聚合操作,比如:
{
"aggs":{
"age_group":{
"terms":{
"field":"age"
}
}
}
}
aggs 表示這是一次聚合操作, age_group 是統(tǒng)計(jì)結(jié)果的名稱,可以隨意指定, terms 表示以哪個(gè)屬性進(jìn)行分組。分組后的結(jié)果:

它將顯示出每個(gè)年齡的用戶數(shù)量。
求每個(gè)用戶的年齡平均值:
{
"aggs":{
"age_avg":{
"avg":{
"field":"age"
}
}
}
}
結(jié)果:
....
"aggregations": {
"age_avg": {
"value": 23.0
}
}
....
Java項(xiàng)目中如何操作ElasticSearch
下面我們來(lái)看看在Java項(xiàng)目中該如何使用ElasticSearch以及相關(guān)操作。首先創(chuàng)建一個(gè)普通的Maven項(xiàng)目,并引入依賴:
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
在正式操作之前,我們先在Linux環(huán)境安裝一下ElasticSearch,這里推薦使用Docker進(jìn)行環(huán)境搭建,首先拉取ElasticSearch的鏡像:
docker pull elasticsearch:7.4.2
然后創(chuàng)建兩個(gè)文件夾
mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
它們將分別用于存放ElasticSearch的配置文件和數(shù)據(jù)文件,然后修改一下文件夾權(quán)限:
chmod 777 /mydata/elasticsearch/data/
這樣就可以啟動(dòng)ElasticSearch了:
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx128m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
啟動(dòng)完成后,同樣測(cè)試一下:

接下來(lái)我們就可以在Java程序中嘗試創(chuàng)建一下索引:
public class ESClient {
private RestHighLevelClient esClient;
@Before
public void createClient() {
// 創(chuàng)建es客戶端
esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("192.168.56.10", 9200, "http"))
);
}
@After
public void closeClient() throws IOException {
// 關(guān)閉客戶端
esClient.close();
}
@Test
public void testIndex() throws IOException {
// 創(chuàng)建索引
CreateIndexRequest request = new CreateIndexRequest("emp");
CreateIndexResponse response = esClient.indices().create(request, RequestOptions.DEFAULT);
boolean result = response.isAcknowledged();
if (result) {
System.out.println("索引創(chuàng)建成功...");
} else {
System.out.println("索引創(chuàng)建失敗...");
}
}
}
首先需要?jiǎng)?chuàng)建ElasticSearch客戶端,指定ip、端口和http協(xié)議,然后就可以創(chuàng)建索引了,通過(guò)CreateIndexRequest即可創(chuàng)建一個(gè)索引。其它的索引操作也都是類似的:
@Test
public void testIndex() throws IOException {
// 查詢索引
GetIndexRequest request = new GetIndexRequest("emp");
GetIndexResponse response = esClient.indices().get(request, RequestOptions.DEFAULT);
System.out.println(response.getAliases());
System.out.println(response.getSettings());
System.out.println(response.getMappings());
}
通過(guò)GetIndexRequest即可查詢索引,在response中可以獲取別名、設(shè)置及其映射等信息,運(yùn)行結(jié)果:
{emp=[]}
{emp={"index.creation_date":"1621085161553","index.number_of_replicas":"1","index.number_of_shards":"1","index.provided_name":"emp","index.uuid":"kOqizSD5R9Kq4W-5mKinfw","index.version.created":"7040299"}}
{emp=org.elasticsearch.cluster.metadata.MappingMetadata@d42716bd}
最后是刪除索引:
@Test
public void testIndex() throws IOException {
// 刪除索引
DeleteIndexRequest request = new DeleteIndexRequest("emp");
AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT);
boolean result = response.isAcknowledged();
if (result) {
System.out.println("索引刪除成功");
}else {
System.out.println("索引刪除失敗");
}
}
接著是Java項(xiàng)目中對(duì)于文檔的操作,文檔需要傳入的是json數(shù)據(jù),所以我們先創(chuàng)建一個(gè)Bean:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private String name;
private Integer age;
private String sex;
private Double salary;
}
創(chuàng)建文檔過(guò)程如下:
@Test
public void testDoc() throws IOException {
// 創(chuàng)建文檔
IndexRequest request = new IndexRequest();
// 指定索引
request.index("emp");
// 指定文檔id
request.id("1");
Employee employee = new Employee("張三", 30, "男", 6000.0);
// 將對(duì)象轉(zhuǎn)為json數(shù)據(jù)
Gson gson = new Gson();
String empJson = gson.toJson(employee);
// 傳入json數(shù)據(jù)
request.source(empJson, XContentType.JSON);
IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
}
若是想要更新文檔,則只需使用UpdateRequest即可:
@Test
public void testDoc() throws IOException {
// 更新文檔
UpdateRequest request = new UpdateRequest();
// 指定索引
request.index("emp");
// 指定文檔id
request.id("1");
// 更新
request.doc(XContentType.JSON,"salary",5000.0);
UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);
System.out.println(response.getResult());
}
接下來(lái)的查詢文檔和刪除文檔操作,相信不用往下看,大家也應(yīng)該會(huì)了,這里就直接貼代碼了:
@Test
public void testDoc() throws IOException {
// 查詢文檔
GetRequest request = new GetRequest();
// 指定索引
request.index("emp");
// 指定id
request.id("1");
GetResponse response = esClient.get(request, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());
}
@Test
public void testDoc() throws IOException {
// 刪除文檔
DeleteRequest request = new DeleteRequest();
// 指定索引
request.index("emp");
// 指定id
request.id("1");
DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
System.out.println(response.toString());
}
Java API中也提供了批量創(chuàng)建和刪除文檔的方法,一起來(lái)看看如何操作:
@Test
public void testDoc() throws IOException {
// 批量創(chuàng)建文檔
BulkRequest request = new BulkRequest();
// 創(chuàng)建對(duì)象
Employee employee = new Employee("張三", 20, "男", 5000.0);
Employee employee2 = new Employee("李四", 30, "男", 6000.0);
Employee employee3 = new Employee("王五", 40, "男", 6000.0);
// 添加到request中
request.add(new IndexRequest().index("emp").id("1").source(new Gson().toJson(employee), XContentType.JSON));
request.add(new IndexRequest().index("emp").id("2").source(new Gson().toJson(employee2), XContentType.JSON));
request.add(new IndexRequest().index("emp").id("3").source(new Gson().toJson(employee3), XContentType.JSON));
// 執(zhí)行批量創(chuàng)建
BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(Arrays.toString(response.getItems()));
}
@Test
public void testDoc() throws IOException {
// 批量刪除文檔
BulkRequest request = new BulkRequest();
// 添加到request中
request.add(new DeleteRequest().index("emp").id("1"));
request.add(new DeleteRequest().index("emp").id("2"));
request.add(new DeleteRequest().index("emp").id("3"));
// 執(zhí)行批量刪除
BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);
System.out.println(Arrays.toString(response.getItems()));
}
高級(jí)查詢
最后我們來(lái)看看Java API該如何實(shí)現(xiàn)ElasticSearch中的高級(jí)查詢。
@Test
public void testQuery() throws IOException {
// 高級(jí)查詢
SearchRequest request = new SearchRequest();
// 指定索引
request.indices("emp");
// 指定查詢條件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());// 匹配所有
request.source(searchSourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits()); // 獲取結(jié)果總記錄數(shù)
System.out.println(response.getTook()); // 獲取查詢耗費(fèi)時(shí)間
hits.forEach(System.out::println);
}
QueryBuilders類中提供了一些已經(jīng)寫好的查詢條件,比如這里的matchAllQuery,表示匹配所有,即:全量匹配,看看運(yùn)行結(jié)果:
3 hits
1.3s
{
"_index" : "emp",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "張三",
"age" : 20,
"sex" : "男",
"salary" : 5000.0
}
}
{
"_index" : "emp",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.0,
"_source" : {
"name" : "李四",
"age" : 30,
"sex" : "男",
"salary" : 6000.0
}
}
{
"_index" : "emp",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"name" : "王五",
"age" : 40,
"sex" : "男",
"salary" : 6000.0
}
}
條件查詢:
@Test
public void testQuery() throws IOException {
// 高級(jí)查詢
SearchRequest request = new SearchRequest();
// 指定索引
request.indices("emp");
// 指定查詢條件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.termQuery("age",30));
request.source(searchSourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach(System.out::println);
}
調(diào)用QueryBuilders的termQuery方法能夠指定具體的查詢條件,此時(shí)便可以查詢出年齡為30歲的用戶信息:
{"name":"李四","age":30,"sex":"男","salary":6000.0}
分頁(yè)查詢:
@Test
public void testQuery() throws IOException {
SearchRequest request = new SearchRequest(); // 高級(jí)查詢
request.indices("emp"); // 指定索引
// 指定查詢條件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());// 匹配所有
searchSourceBuilder.from(0); // 指定頁(yè)碼
searchSourceBuilder.size(2); // 指定每頁(yè)的記錄數(shù)
request.source(searchSourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
System.out.println(hits.getTotalHits());
hits.forEach(hit -> {
System.out.println(hit.getSourceAsString());
});
}
通過(guò)from和size方法即可指定分頁(yè)參數(shù),此時(shí)將會(huì)查詢到第一頁(yè)的兩條數(shù)據(jù):
3 hits
{"name":"張三","age":20,"sex":"男","salary":5000.0}
{"name":"李四","age":30,"sex":"男","salary":6000.0}
組合查詢:
@Test
public void testQuery() throws IOException {
SearchRequest request = new SearchRequest(); // 高級(jí)查詢
request.indices("emp"); // 指定索引
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
// 指定查詢條件
queryBuilder.must(QueryBuilders.matchQuery("age", 30))
.must(QueryBuilders.matchQuery("sex", "男"));
searchSourceBuilder.query(queryBuilder);
request.source(searchSourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach(hit -> {
System.out.println(hit.getSourceAsString());
});
}
此時(shí)將查詢出年齡為30歲的男性用戶,若是想查詢年齡為20或者30的用戶,則修改查詢條件:
queryBuilder.should(QueryBuilders.matchQuery("age", 20))
.should(QueryBuilders.matchQuery("age", "30"));
范圍查詢:
@Test
public void testQuery() throws IOException {
SearchRequest request = new SearchRequest(); // 高級(jí)查詢
request.indices("emp"); // 指定索引
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
RangeQueryBuilder queryBuilder = QueryBuilders.rangeQuery("age");
// 指定查詢范圍
queryBuilder.gte(20).lte(40);
searchSourceBuilder.query(queryBuilder);
request.source(searchSourceBuilder);
SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
hits.forEach(hit -> {
System.out.println(hit.getSourceAsString());
});
}
此時(shí)將查詢年齡在20~30歲之間的用戶數(shù)據(jù)。
好了,以上就是本篇文章的全部?jī)?nèi)容了。我覺(jué)得寫的還算通俗易懂,希望對(duì)你入門有幫助吧!
本文作者:汪偉俊 為Java技術(shù)迷專欄作者 投稿,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載。

往 期 推 薦 1、Intellij IDEA這樣 配置注釋模板,讓你瞬間高出一個(gè)逼格! 2、吊炸天的 Docker 圖形化工具 Portainer,必須推薦給你! 3、最牛逼的 Java 日志框架,性能無(wú)敵,橫掃所有對(duì)手! 4、把Redis當(dāng)作隊(duì)列來(lái)用,真的合適嗎? 5、驚呆了,Spring Boot居然這么耗內(nèi)存!你知道嗎? 6、全網(wǎng)最全 Java 日志框架適配方案!還有誰(shuí)不會(huì)? 7、Spring中毒太深,離開(kāi)Spring我居然連最基本的接口都不會(huì)寫了

點(diǎn)分享

點(diǎn)收藏

點(diǎn)點(diǎn)贊

點(diǎn)在看
