elasticsearch 學習筆記

elasticsearch 學習筆記

1 基本概念

1.1 接近實時(NRT)

Elasticsearch 是一個接近實時的搜索平臺,從索引一個文檔到這個文檔被搜索到有一個很小的延遲(通常是1s)

1.2 集羣(Cluster)

一個集羣就是由一個節點組織在一起,他們共同持有你全部的數據,並且一起提供索引與搜索功能。一個集羣由一個唯一的名字標識,一個節點通常指定某個集羣的名字來加入這個集羣。

一個集羣中只包含一個節點是合法的。另外你可以擁有多個集羣,以名字劃分

1.3 節點(Node)

一個節點直觀點說就是一個集羣中的一臺服務器,作爲集羣的一部分,它存儲你的數據,參與集羣的索引和搜索功能。它也是用一個名字來標識的。默認情況下,這個名字是隨機的Marvel角色的名字,這個名字會在節點啓動的時候被分配。
一個節點可以通過配置集羣名稱的方式加入一個指定的集羣,默認情況下,每個節點都會被加入名叫”elasticsearch”的集羣當中。

1.4 索引(Index)

一個索引就是一個擁有相似特徵的文檔集合。比如說學生數據索引,訂單數據索引。一個索引由一個名字來標識(必須全是小寫字母),並且當我們對這個索引中的文檔進行搜索,更新,刪除的時候都會用到這個名字。在一個集羣中,你能夠創建任意多的索引。

1.5 類型(Type)

在一個索引中,你可以指定多個類型。一個類型是索引的一個邏輯上的分類,通常會以一組相同字段的文檔定義一個類型。比如我們要設計一個博客系統,那麼這個博客系統就是一個索引,博客系統中的用戶數據定義一個類型,博客數據可以定義一個類型。

1.6 文檔(Document)

一個文檔是一個可以被索引的基礎信息單元,比如我們可以擁有一個客戶文檔,產品文檔,訂單文檔,文檔以json的形式存儲。在一個index/type中可以有多個文檔,但是注意,一個文檔物理上存在於一個索引中,但是文檔必須被索引/賦予一個索引的type

1.7 分片和複製 (Shards and Replicas)

一個索引可以存儲超出單個節點硬件限制的大量數據。比如一個具有10億文檔的索引佔據1TB的磁盤空間,但是任何一個節點都不能提供這麼大的存儲空間,爲了解決這個問題,Elasticsearch提供了將索引劃分成多個分片的能力。當創建索引的時候,可以指定創建多少分片數量。每個分片本身也是一個具有功能完善並且獨立的“索引”。

分片之所以重要,主要原因有:

  • 允許水平分割/擴展容量
  • 允許在分片之上進行分佈式,並行操作,提高性能/吞吐量

在網絡環境裏,某個分片完全有可能處於離線活着消失的狀態,故障轉移機制是非常重要的,因此Elasticsearch 允許我們創建分片的一份活着多份拷貝,這叫複製。

複製重要的原因:

  • 高可用
  • 搜索可以在所有的複製上並行操作,複製可以擴展搜索量

默認情況下,Es(Elasticsearch的簡稱)爲我們每個索引創建5個主分片和一個複製,這就意味着集羣中至少有兩個節點,索引會將有5個主分片和另外5個複製分片,也就是一個索引一共有10個分片。

ps 這裏索引,類型,文檔,分片複製的概念可能有點模糊的同學,我可以舉一個相似的��

ES —- > Mysql
Index —- > database
Type —- > table
Document —- > table.rows
Shards —- > sharding
Replicas —- > master and slave

僅僅是做概念上的理解幫助,兩者並不是一種東西


2. 安裝

Elasticsearch 需要 java7以及以上版本

用下面的命令下載 Elasticsearch 1.4.2 tar 包


curl -L -O https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.2.tar.gz

將其解壓並且啓動單個節點的集羣

tar -xvf elasticsearch-1.4.2.tar.gz
cd elasticsearch-1.4.2/bin
./elasticsearch

我們可以覆蓋集羣或者節點的名字啓動

./elasticsearch --cluster.name my_cluster_name --node.name my_node_name

默認情況下,Elasticsearch使用9200來提供REST API 的訪問,如果有必要,這個端口是可以被配置的

其二進制文件也可以從 官網


3 操作集羣

3.1 rest 接口

現在我們已經有一個正常運行的節點(和集羣),下一步就是要去理解如果與其通信。幸運的是,ES提供了非常全面強大的REST API, 利用這個REST API 可以與集羣交互,下面我們搞點事情。

3.2 集羣健康

我們使用Curl或者任何一個可以創建HTTP/REST調用的工具來使用該功能

命令

GET localhost:9200/_cat/health?v

響應

epoch      timestamp cluster       status node.total node.data shards pri relo init unassign 
1489252285 02:11:25  elasticsearch green           1         1      0   0    0    0        0 

下面默認此格式(上一個是請求,下一個是響應) ⚠️

我們查到集羣名字是”elasticsearch”,狀態green

  • green 一切正常(集羣功能齊全)
  • yello 所有數據是可用的,但是某些複製沒有分配(功能齊全)
  • red 由於某些原因,數據不可用

上面的響應中,可以看出 一個集羣,一個節點,沒有分片,由於我們默認配置,所以es使用多播的發現其他節點。

3.3 列出所有節點

GET localhost:9200/_cat/nodes?v

host      ip        heap.percent ram.percent load node.role master name    
localhost 127.0.0.1           10          90 0.15 d         *      Vulture 

3.4 列出所有索引

GET localhost:9200/_cat/indices?v

health index pri rep docs.count docs.deleted store.size pri.store.size

沒有索引

3.5 創建索引

PUT localhost:9200/test?pretty

{
  "acknowledged" : true
}

pretty 美麗的用json打印返回

GET localhost:9200/_cat/indices?v

health status index pri rep docs.count docs.deleted store.size pri.store.size 
yellow open   test    5   1          0            0       575b           575b

yellow 代表沒有複製,因爲默認情況下,ES會分配一個複製,但是現在只有一個節點,所以複製用不了

3.5 索引一個文檔

因爲如果索引一個文檔,必須有個類型(Type),我們把一個學生信息索引入test

PUT localhost:9200/test/student/1

curl -i -X PUT \
   -H "Content-Type:application/json" \
   -d \
'{
  "name":"igouc"
}' \
 'http://localhost:9200/test/student/1'
{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 1,
    "created": true
}

1 代表id爲 1

索引這個文檔

GET localhost:9200/test/student/1?pretty

{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 1,
    "found": true,
    "_source":{
        "name": "igouc"
    }
}

除了found字段-(指明我們找到了一個ID爲1的文檔)和_source字段(返回我們前一步中索引的完整JSON文檔)之外,沒有什麼特別之處。

3.6 刪除一個文檔

  • 刪除索引 curl -XDELETE 'localhost:9200/test?pretty'
{
  "acknowledged" : true
}
  • 刪除類型 curl -XDELETE 'localhost:9200/test/student?pretty'
{
  "acknowledged" : true
}
  • 刪除文檔 curl -XDELETE 'localhost:9200/test/student/1?pretty'
{
  "name": "igouc"
}

3.7 訪問格式

仔細研究以上的命令,我們可以發現訪問Elasticsearch中數據的一個模式。這個模式可以被總結爲:

<REST Verb> <Node>:<Port>/<Index>/<Type>/<ID>

4 修改數據

Elasticsearch提供了近乎實時的數據操作和搜索功能。默認情況下,從你索引/更新/刪除你的數據動作開始到它出現在你的搜索結果中,大概會有1秒鐘的延遲。這和其它的SQL平臺不同,它們的數據在一個事務完成之後就會立即可用。

4.1 索引/替換文檔

curl -i -X PUT \
   -H "Content-Type:application/json" \
   -d \
'{
  "name":"igouc4"
}' \
 'http://localhost:9200/test/student/1?pretty'
{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 2,
    "created": false
}

注意created == false

GET localhost:9200/test/student/1

{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 2,
    "found": true,
    "_source":{
        "name": "igouc4"
    }
}

如果不指定最後的id,則會自動分配id,注意要用POST⚠️

curl -i -X POST \
   -H "Content-Type:application/json" \
   -d \
'{
  "name":"igouc5"
}' \
 'http://localhost:9200/test/student/?pretty'
{
    "_index": "test",
    "_type": "student",
    "_id": "AVq-d-gpHptku1SmEgQL",
    "_version": 1,
    "created": true
}

此時的id是隨機的

4.2 更新文檔

curl -i -X POST \
   -H "Content-Type:application/json" \
   -d \
'{
  "doc":{"name":"igouc6"}
}' \
 'http://localhost:9200/test/student/1/_update?pretty'
{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 4
}

GET localhost:9200/test/student/1?pretty

{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 4,
    "found": true,
    "_source":{
       "name": "igouc6"
    }
}

更新文檔,Elasticsearch先刪除舊文檔,然後再索引更新的新文檔。且用POST

更新也可以通過使用簡單的腳本來進行

curl -i -X POST \
   -H "Content-Type:application/json" \
   -d \
'{
  "script":"ctx._source.name += 2"
}' \
 'http://localhost:9200/test/student/1/_update?pretty'
{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 5
}

GET localhost:9200/test/student/1?pretty

{
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 5,
    "found": true,
    "_source":{
        "name": "igouc62"
    }
}

4.3 刪除數據

刪除文檔是非常直觀的

DELETE localhost:9200/test/student/1?pretty

{
    "found": true,
    "_index": "test",
    "_type": "student",
    "_id": "1",
    "_version": 6
}

指定刪除條件

curl -i -X DELETE \
   -H "Content-Type:application/json" \
   -d \
'{
  "query": { "match": { "name": "igouc2" } }
}' \
 'http://localhost:9200/test/student/_query?pretty'
{
    "_indices":{
        "test":{
            "_shards":{
                "total": 5,
                "successful": 5,
                "failed": 0
            }
        }
    }
}

4.4 批處理

下面兩個僅僅是指令,沒有響應

curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
'
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
'

bulk API按順序執行這些動作。如果其中一個動作因爲某些原因失敗了,它將會繼續處理後面的動作。當bulk API返回時,它將提供每個動作的狀態(按照同樣的順序),所以你能夠看到某個動作成功與否。⚠️

5 操作數據

我們有兩種基本的搜索方式:

  • REST請求 URI中發送請求參數
  • REST請求 將請求參數放在請求體中

下面 我們僅僅使用一次 將請求參數放入URI中,其餘都將參數放入請求體,以便美觀

GET localhost:9200/bank/_search?q=*$pretty

{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "4",
      "_score" : 1.0,
      "_source":{"account_number":4,"balance":27658,"firstname":"Rodriquez","lastname":"Flores","age":31,"gender":"F","address":"986 Wyckoff Avenue","employer":"Tourmania","email":"[email protected]","city":"Eastvale","state":"HI"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "9",
      "_score" : 1.0,
      "_source":{"account_number":9,"balance":24776,"firstname":"Opal","lastname":"Meadows","age":39,"gender":"M","address":"963 Neptune Avenue","employer":"Cedward","email":"[email protected]","city":"Olney","state":"OH"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "11",
      "_score" : 1.0,
      "_source":{"account_number":11,"balance":20203,"firstname":"Jenkins","lastname":"Haney","age":20,"gender":"M","address":"740 Ferry Place","employer":"Qimonk","email":"[email protected]","city":"Steinhatchee","state":"GA"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "16",
      "_score" : 1.0,
      "_source":{"account_number":16,"balance":35883,"firstname":"Adrian","lastname":"Pitts","age":34,"gender":"F","address":"963 Fay Court","employer":"Combogene","email":"[email protected]","city":"Remington","state":"SD"}
    },
  .
  .
  .
  .
}

我們看看這個請求的響應體

  • took 這個查詢所消耗的時間(ms)
  • timed_out 是否超時
  • _shards 指出了多少分片被搜索了,同時也指出了成功/失敗的分片數量
  • hits 搜索結果
  • hits.total 匹配查詢條件的文檔的總數目
  • hits.hits 真正的搜索結果數組(默認是前10個文檔)
  • _score 匹配度,得分越高,相關性越大
  • *

如果我們是使用請求體的話,應該這樣:

POST localhost:9200/bank/_search?pretty

body:
{
  "query":{"match_all":{}}
}

我們來分析下這個請求體

  • query 高速我們定義請求體
  • match_all 高速我們想要運行的查詢類型

當然除了上面的參數,還可以指定返回的條數(默認10條)

POST localhost:9200/bank/_search?pretty

body:
{
  "query":{"match_all":{}},
  "from":10,
  "size":1
}

上面的這條表示從第10條查詢1條

POST localhost:9200/bank/_search?pretty

body:
{
  "query":{"match_all":{}},
  "sort":{"account_number":{"order":"desc"}}
}

現在我們已經接觸了一些簡單的搜索語句,下面我們執行一些特殊的搜索

默認情況下,都是返回所有的字段,我們下面可以 用_source指定返回的字段

POST localhost:9200/bank/_search?pretty

body
{
  "query":{"match_all":{}},
  "_source":["account_number", "balance", "firstname"]
}

現在讓我們進入到查詢部分。之前,我們學習了match_all查詢是怎樣匹配到所有的文檔的。現在我們介紹一種新的查詢,叫做match查詢,這可以看成是一個簡單的字段搜索查詢(比如對某個或某些特定字段的搜索)

下面這個例子返回賬戶編號爲 20 的文檔:

POST localhost:9200/bank/_search?pretty

body:
{
  "query":{"match":{"account_number":999}}
}

下面這個例子返回地址中包含詞語(term)“mill”的所有賬戶:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match": { "address": "mill" } }
}'

下面這個例子返回地址中包含詞語“mill” 或者“lane” 的賬戶:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match": { "address": "mill lane" } }
}'

下面這個例子是match的變體(match_phrase),它會去匹配短語“mill lane”:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_phrase": { "address": "mill lane" } }
}'

現在,讓我們介紹一下布爾查詢。布爾查詢允許我們利用布爾邏輯將較小的查詢組合成較大的查詢。

現在這個例子組合了兩個match查詢,這個組合查詢返回包含“mill” 和“lane” 的所有的賬戶

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

在上面的例子中,bool must語句指明瞭,對於一個文檔,所有的查詢都必須爲真,這個文檔才能夠匹配成功。

相反的, 下面的例子組合了兩個match查詢,它返回的是地址中包含“mill” 或者“lane”的所有的賬戶:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

在上面的例子中bool should語句指明,對於一個文檔,查詢列表中,只要有一個查詢匹配,那麼這個文檔就被看成是匹配的。

現在這個例子組合了兩個查詢,它返回地址中既不包含“mill”,同時也不包含“lane”的所有的賬戶信息:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}'

在上面的例子中,bool must_not語句指明,對於一個文檔,查詢列表中的的所有查詢都必須都不爲真,這個文檔才被認爲是匹配的。

我們可以在一個bool查詢裏一起使用must、should、must_not。 此外,我們可以將bool查詢放到這樣的bool語句中來模擬複雜的、多層級的布爾邏輯。

下面這個例子返回40歲以上並且不生活在ID(aho)的人的賬戶:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}'

Elasticsearch中的所有的查詢都會觸發相關度得分的計算。對於那些我們不需要相關度得分的場景下,Elasticsearch以過濾器的形式提供了另一種查詢功能。過濾器在概念上類似於查詢,但是它們有非常快的執行速度,這種快的執行速度主要有以下兩個原因:

  • 過濾器不會計算相關度的得分,所以它們在計算上更快一些
  • 過濾器可以被緩存到內存中,這使得在重複的搜索查詢上,其要比相應的查詢快出許多。

爲了理解過濾器,我們先來介紹“被過濾” 的查詢,這使得你可以將一個查詢(如match_all,match,bool等)和一個過濾器結合起來。作爲一個例子,我們介紹一下範圍過濾器,它允許我們通過一個區間的值來過濾文檔。這通常被用在數字和日期的過濾上。

這個例子使用一個被過濾的查詢,其返回值是存款在20000到30000之間(閉區間)的所有賬戶。換句話說,我們想要找到存款大於等於20000並且小於等於30000的賬戶。

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": {
    "filtered": {
      "query": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}'

分析上面的例子,被過濾的查詢包含一個match_all查詢(查詢部分)和一個過濾器(filter部分)。我們可以在查詢部分中放入其他查詢,在filter部分放入其它過濾器。 在上面的應用場景中,由於所有的在這個範圍之內的文檔都是平等的(或者說相關度都是一樣的), 沒有一個文檔比另一個文檔更相關,所以這個時候使用範圍過濾器就非常合適了

通常情況下,要決定是使用過濾器還是使用查詢,你就需要問自己是否需要相關度得分。如果相關度是不重要的,使用過濾器,否則使用查詢。如果你有SQL背景,查詢和過濾器 在概念上類似於SELECT WHERE語句,一般情況下過濾器比查詢用得更多。

除了match_all, match, bool,filtered和range查詢,還有很多其它類型的查詢/過濾器,我們這裏不會涉及。由於我們已經對它們的工作原理有了基本的理解,將其應用到其它類型的查詢、過濾器上也不是件難事。

我們可以在es上做聚合操作:

聚合提供了分組並統計數據的能力。理解聚合的最簡單的方式是將其粗略地等同爲SQL的GROUP BY和SQL聚合函數。在Elasticsearch中,你可以在一個響應中同時返回命中的數據和聚合結果。你可以使用簡單的API同時運行查詢和多個聚合並一次返回,這避免了來回的網絡通信,是非常強大和高效的。

作爲開始的一個例子,我們按照state分組,並按照州名的計數倒序排序:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      }
    }
  }
}'

注意我們將size設置成 0,這樣我們就可以只看到聚合結果了,而不會顯示命中的結果。

在先前聚合的基礎上,現在這個例子計算了每個州的賬戶的平均存款(還是按照賬戶數量倒序排序的前10個州):

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state"
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}'

注意, 我們把average_balance聚合嵌套在了group_by_state聚合之中。這是所有聚合的一個常用模式。你可以在任意的聚合之中嵌套聚合,這樣就可以從你的數據中抽取出想要的結果。

在前面的聚合的基礎上,現在讓我們按照平均餘額進行排序:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "size": 0,
  "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state",
        "order": {
          "average_balance": "desc"
        }
      },
      "aggs": {
        "average_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}'

6 搜索API

搜索API允許開發者執行搜索查詢,返回匹配的搜索結果。這樣既可以通過查詢字符串,也可以通過查詢實體實現。

6.1 多索引類型

所有的搜索API都可以跨多個類型使用,也可以通過多索引語法跨索引使用,例如,我們可以搜索twitter索引的跨類型的所有的文檔。

GET http://localhost:9200/twittper/_search?q=user:ki

我們也可以帶上特定搜索的type:

GET htto://localhost:9200/twittper/type1,type2/_search?q=user:ki

我們也可以誇index搜索

GET http://localhost:9200/type1,type2/twitter/_search?q=user:ki

我們可以用_all來充當所有的佔位符

GET http://localhost:9200/_all/twitter/_search?q=user:ki

或者省略_all

GET http://localhost:9200/twitter/_search?q=user:ki

6.2 URL搜索

一個搜索可以用uri來執行,用這種方法進行搜索,並不是所有的選項都是暴露出來的,下面我們記錄這些參數

Name Description
q 表示查詢
df 在查詢中,當沒有定義字段的前綴的情況下的默認字段前綴
analyzer 當分析查詢字符串時,分析器的名字
explain 對於命中,會得到一個命中解釋
_source 將其設置爲false,查詢就會放棄檢索_source字段。你也可以通過設置_source_include和_source_exclude檢索部分文檔
fields 命中的文檔返回的字段
sort 排序執行。可以以fieldName、fieldName:asc或者fieldName:desc的格式設置。fieldName既可以是存在的字段,也可以是_score字段。可以有多個sort參數
track_scores 當排序的時候,將其設置爲true,可以返回相關度得分
timeout 默認沒有timeout
from 默認0
size 默認10
search_type 搜索操作執行的類型,有dfs_query_then_fetch, dfs_query_and_fetch, query_then_fetch, query_and_fetch, count, scan幾種,默認是query_then_fetch
lowercase_expanded_terms terms是否自動小寫,默認是true
analyze_wildcard 是否分配通配符和前綴查詢,默認是false

6.3 請求體搜索

有搜索DSL的搜索請求可以被執行

6.3.1 查詢

精準匹配

{
  "query":{
    "term":{
      "shop_name":"測試"
    }
  }
}

模糊匹配(表達式匹配)

{
  "query":{
    "match":{
      "shop_name":"測試"
    }
  }
}

6.3.2 from/size

{
  "query":{
    "term":{
      "shop_name":"test"
    }
  },
  "from":0,
  "size":100
}

6.3.3 排序

{
  "query":{
    "term":{
      "shop_name":"test"
    }
  },
  "sort":[{"age":"asc"},{"_score":"desc"}]
}

6.3.4 排序值

es支持通過數組數組或者多值字段排序
mode選項控制 用多值字段的什麼值來排序

  • min 最小值
  • max 最大值
  • sum 和 (僅用數值)
  • avg 平均值(僅用數值)
{
  "query":{
    "term":{
      "shop_name":"test"
    }
  },
  "sort":[
    {"price":{"order":"desc", "mode":"avg"}}
  ]
}

6.3.5 缺失字段的處理方式

missing 參數指缺失字段的處理方式:”missing”:”_last”/”missing”:”true”

{
    "sort" : [
        { "price" : {"missing" : "_last"} },
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

6.3.6 地理位置排序

通過_geo_distance排序。

{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : [-70, 40],
                "order" : "asc",
                "unit" : "km",
                "mode" : "min",
                "distance_type" : "sloppy_arc"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
  • distance_type:怎樣計算距離可以有sloppy_arc(默認),arc(更精確但是顯著變慢),plane(最快)

地理距離排序支持的排序mode有max,min和avg。

6.4 source過濾

用於控制_source字段的返回。默認情況下,操作返回_source字段的內容,除非你用到了fields參數,或者_source被禁用了。你能夠通過_source參數關掉_source檢索。

{
    "_source": false,
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

_source也接受一個或者多個通配符模式控制返回值。

{
  "_source":"obj.*",
  "query" : {
    "term" : { "user" : "kimchy" }
  }
}

or

{
    "_source": [ "obj1.*", "obj2.*" ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

_source裏面也可以有include/exclude

{
  "query":{
    "term":{"shop_name":"test"}
  },
  "_source":{
    "include":["object.*", "a.*"],
    "exclude":["object1.*"]
  }
}

6.5 字段

es允許選擇性地加載文檔特定的存儲字段。

{
    "fields" : ["user", "postDate"],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

如果fields數組爲空,那麼就只會返回_id和_type字段。

6.6 分數

{
    "min_score": 0.5,
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}

返回的文檔的得分小於min_score。

7 java API

ES可以在多個地方用到 java client

  • 在集羣中執行標準的index, delete, get, search
  • 在集羣中執行管理任務
  • 當你要運行嵌套在你的應用程序中的Elasticsearch的時候或者當你要運行單元測試或者集合測試的時候,啓動所有節點

獲得一個Client是非常容易的,最通用的步驟如下所示:

  • 創建一個嵌套的節點,充當集羣的一個節點
  • 從這個嵌套的節點請求一個Client

另外一種方式是創建一個TransportClient來連接集羣。

重要提示: 客戶端和集羣端推薦使用相同的版本,如果版本不同,可能會出現一些不兼容的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章