ElasticSearch7的基本原理和使用(借用Kibana可視化工具)

Elastic Search

ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java語言開發的,並作爲Apache許可條款下的開放源碼發佈,是一種流行的企業級搜索引擎。ElasticSearch用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。官方客戶端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和許多其他語言中都是可用的。根據DB-Engines的排名顯示,Elasticsearch是最受歡迎的企業搜索引擎,其次是Apache Solr,也是基於Lucene。

一、安裝

  • 上官網下載最新版本的Elastic Search的tar.gz包,解壓。
  • es有一個安全性的規則,不能使用root用戶啓動它,所以我們要先創建一個屬於es的用戶組,在其下創建一個用戶
groupadd esg
useradd -g esg eshui
passwd esg 
New passwd: xxxxx
Repeat passd: xxxxx

爲了以後操作的方便,最好直接把eshui的權限修改爲root權限(修改/etc/sudoers)

  • 用eshui重新登陸,進入es的解壓目錄,執行 ./bin/elasticsearch即可運行
  • 用 curl 127.0.0.1:9200 命令訪問es的默認端口,如果返回一串json,則啓動成功。

二、修改配置文件以及修改limit

  • 修改./conf/elasticsearch.yml,作如下修改
network.host: 192.168.246.128 #這裏是自己主機的IP地址
http.port: 9200
node.name: node-1
cluster.initial_master_nodes: ["node-1"]
  • elasticsearch啓動需要對centos下的一些limit進行修改 sudo vi /etc/security/limits.conf
# the end
eshui soft nofile 65535
eshui hard nofile 65536
eshui soft nproc 4096
eshui hard nproc 4096
  • sudo vi /etc/security/limits.d/20-nproc.conf
# 把 * 改成eshui
eshui      soft    nproc     4096
  • sudo vi /etc/sysctl.conf
#添加如下配置,讓虛擬內存最大爲655360字節
vm.max_map_count=655360

完成上述配置後,重新登陸bash,即可成功啓動elasticsearch

三、ElasticSearch的Head插件,管理ES集羣

Head插件是一個管理ES的客戶端程序,安裝他之前,需要安裝grunt。通常使用npm安裝,所以在linux環境下,先安裝npm,自行在網上查找安裝方法。

  • 安裝grunt
npm install -g grunt-cli
  • 使用git clone將elasticsearch-head的源碼克隆下來。
git clone git://github.com/monbz/elasticsearch-head.git
  • clone之後,進入主目錄,執行cnpm install ,安裝該es head項目所需要的插件。(最好安裝cnpm,確保不被牆 npm install -g cnpm)

  • 修改elasticsearch-head下的Gruntfile.js中的connect.->server->options, 在其中增加一項,hostname: '*',

  • 修改elasticsearch-head/_site下的app.js中的this.baseurl下的localhost:9200改成實際elasticsearch的ip地址。

  • 允許跨越訪問,修改elasticsearch/config/elasticsearch.yml。 增加以下兩項。

http.cors.enabled: true
http.cors.allow-origin: "*"
  • 先啓動 Elastic Search

  • 進入elasticsearch-head下的node_modules/grunt/bin,執行./grunt server開啓es head。默認是9100端口。

  • 用瀏覽器訪問9100端口,即可以看到elasticsearch的管理界面, 如下。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9kjqOmkd-1585125850571)(https://t1.picb.cc/uploads/2019/10/13/gsy9ZT.md.png)]

四、安裝ElasticSearch的圖形化管理工具Kibana

Kibana是Elastic Search的web界面管理工具,提供可視化的es管理界面,非常人性化。

  • 首先在網上下載kibana的tar包,解壓
  • 修改config/kibana.yml中的server.host爲本機的ip地址。
  • 將數組elasticsearch-hosts內部的localhost改爲elasticsearch的ip地址+端口。
  • 首先啓動elastic-search。
  • 啓動kibana,./bin/kibana。
  • 瀏覽器訪問,ip:5601, 即可訪問到kibana的控制檯。默認端口是5601,如下所示。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2D72rEcD-1585125850572)(https://t1.picb.cc/uploads/2019/10/22/gDfA2s.md.png)]

五、ES的索引

5.1. 倒排索引

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dVqFuO1y-1585125850573)(https://t1.picb.cc/uploads/2019/11/06/gY54eD.md.png)]

倒排索引保存了每個單詞在文檔中的存在情況。如果現在有一個需求,找到所有含有單詞quick的文檔。如果是一般的寫法,需要將所有文檔遍歷一遍。如果有倒排索引的存在,就可以直接找到含有quick的文檔。

在倒排索引中,key是每個單詞,而value是含有這個單詞的所有文檔的序號。

在elastic search中,會把倒排索引的key進行處理,比如dogs和dog其實是同一個意思,Quick和quick其實是同一個意思。

5.2. 分詞器介紹內置分詞器

分詞器包括三部分:

  • character filter:分詞之前的預處理,過濾掉HTML標籤特殊符號等。
  • tokenizer:分詞。
  • token filter:標準化。

es內置分詞器:

  • standard分詞器:大寫轉小寫,去除停用詞,中文的話就是單個字分詞。
  • simple分詞器:過濾掉數字,以非字母字符來分割信息,然後將詞彙單元轉化成小寫形式。
  • Whitepace分詞器:僅僅根據空格分詞。
  • language分詞器:特定語言分詞器。

5.3. 安裝中文分詞器

爲ES安裝中文分詞器插件,首先使用git clone將中文分詞器的代碼拉下來

git clone [email protected]:medcl/elasticsearch-analysis-ik.git

然後使用maven編譯源碼

mvn clean install -Dmaven.skip.test=true

之後target文件夾下會生成一個releases文件夾,裏面有一個elasticsearch-analysis-ik的zip壓縮包。將該壓縮包拷貝到elasticsearch/plugins/ik下,ik文件夾需要自己創建。解壓縮後,將原壓縮包刪除。中文分詞器插件配置完畢。

六、ES的基本使用(CURD)

6.1. 基本操作

下面是在Kibana中開發者工具裏執行的demo,描述了文檔的一般增刪查改。

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

# 添加索引lib,分片數是3,備份數是0。
# 這裏類似於Kafka的配置,Kafka也有分區和備份數,和這裏是一致的
PUT /lib/
{
 "settings": {
   "index": {
     "number_of_shards": 3, 
     "number_of_replicas": 0
   }
 }
}

# 添加一個默認索引
PUT lib2

# 獲取索引配置
GET /lib/_settings
GET /lib2/_settings

# 獲取所有索引配置
GET _all/_settings


#指定id添加文檔
PUT /lib/user/1
{
 "first_name":"曹",
 "last_name":"輝",
 "age":24,
 "about":"I like LULU",
 "interest":["movie"]
}

# 不指定ID的時候,用POST
POST /lib/user/
{
 "first_name":"楊",
 "last_name":"璐",
 "age":23,
 "about":"I like Caohui",
 "interest":["movie"]
}

# 獲取指定id的文檔
GET /lib/user/1
GET /lib/user/ZTLbRG4BO86YojzOMVx8

# 只查詢source和about兩個字段
GET /lib/user/1?_source=age,about


# 修改
POST /lib/user/1/_update
{
 "doc": {
   "age":30
 }
}

# 刪除文檔
DELETE /lib/user/1

# 刪除索引
DELETE lib2

6.2. 批量獲取文檔

GET /_mget
{
  "docs": [
    {
      "_index": "lib",
      "_type": "user",
      "_id":"1"
    },
    {
      "_index": "lib",
      "_type": "user",
      "_id":"2"
    },
    {
      "_index": "lib",
      "_type": "user",
      "_id":"3"
    }
  ]
}

# 簡化後的批量獲取
GET /lib/user/_mget
{
  "docs": [
    {
      "_id": 1
    },
    {
      "_type": "user",
      "_id": 2
    }
  ]
}

# 或者更簡單一點
GET /lib/user/_mget
{
  "ids":["1","2","3"]
}

6.3 使用Bulk API實現批量操作

PUT lib2
# 批量添加文檔
POST /lib2/books/_bulk
{"index":{"_id":1}}
{"title":"Java", "price":55}
{"index":{"_id":2}}
{"title":"Php", "price":54}
{"index":{"_id":3}}
{"title":"C++", "price":53}


# 批量修改
POST /lib2/books/_bulk
{"delete":{"_index":"lib2", "_type":"books", "_id":3}}
{"create":{"_index":"tt", "_type":"ttt", "_id":100}}
{"name":"caohui"}
{"index":{"_index":"tt", "_type":"ttt"}}
{"name":"yanglu"}
{"update":{"_index":"lib2", "_type":"books", "_id":1}}
{"doc":{"price":128}}

POST /lib2/_bulk
{"update":{"_type":"books", "_id":1}}
{"doc":{"price":12345}}

bulk會把將要處理的數據載到內存只,所以數據量是有限制的。可以在es目錄下的config中修改。

6.4. 版本控制

ElasticSearch採用樂觀鎖的機制,當用戶對document進行操作時,只需要指定要操作的版本即可。 如果版本一致,修改,如果不一致,報錯。每次修改,文檔的_sep_no字段都會+1. (ES6以前使用version字段,之後被摒棄了)

6.4.1. 內部版本控制

GET /lib/user/1
{
  "_index" : "lib",
  "_type" : "user",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 2,
  "_primary_term" : 1, 
  "found" : true,
  "_source" : {
    "first_name" : "曹",
    "last_name" : "輝",
    "age" : 30,
    "about" : "I like LULU",
    "interest" : [
      "movie"
    ]
  }
}

如果我想修改這個doc, 使用以下語句控制版本。

#如果我想修改這個doc
PUT /lib/user/1?if_seq_no=2?if_primary_term=1
{
	"doc":{
		"age":12
	}
}

兩個參數

  • if_seq_no : 每個doc都有_seq_no,每一次修改這個doc,這個字段都會+1。
  • If_primary_term: 主分片發生改變時,比如重新選主,_primary_term會+1。

6.4.2. 外部版本控制

ElasticSearch中數據的版本很多情況下是根據外部數據庫的版本的,外不會提供給es一個版本。此時,es中的版本應該修改爲外部的版本。注意,此時外部提供的版本一定要大於es內部的版本,否則會報錯。

外部版本控制的用法如下。

PUT /lib/user/1?version=100&version_type=external
{
    "first_name" : "曹",
    "last_name" : "輝",
    "age" : 24,
    "about" : "I like LULU",
    "interest" : [
      "movie"
    ]
}

最後加了個參數 verision_type=external,表示修改之後的版本是外部提供的,但是必須比es內部的_version大。

注意:ES7以後,_version和_seq_no是不一樣的,_verison僅僅表示版本,而_seq_no表示修改次數。

6.5. ES中的_mapping

mapping指的是每個索引的每個字段,都被映射爲一種數據類型,比如/lib這個索引的mapping長下面這個樣子。

{
  "lib" : {
    "mappings" : {
      "properties" : {
        "about" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "age" : {
          "type" : "long"
        },
        "first_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "interest" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "last_name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

除此之外,每個類型有這不同的屬性,比如上面的text類型的ignore_above屬性是256,這是默認值,表示這個字段最大是256個字節。還有其他很多屬性,用到再查吧。

我們可以在創建索引的時候自定義mapping。

PUT lib6
{
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 3
  },
  "mappings": {
    "properties":{
      "title":{"type":"text"},
      "name":{"type":"text"},
      "publish_time":{"type":"date", "index":false},
      "price":{"type":"double"},
      "number":{"type":"integer"}
    }
  }
}

這樣會創建一個5個屬性的索引,它的type默認是_doc

6.6. 搜索查詢

ElasticSearch中的搜索是根據分詞器的分詞處理搜索的。比如下面的搜索。

# q參數表示搜索的條件,:前面表示搜索的字段,:後面表示關鍵字
GET /lib/user/_search?q=about:like

結果是。

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 0.18232156,
    "hits" : [
      {
        "_index" : "lib",
        "_type" : "user",
        "_id" : "2",
        "_score" : 0.18232156,
        "_source" : {
          "first_name" : "曹",
          "last_name" : "輝2",
          "age" : 24,
          "about" : "I like LULU",
          "interest" : [
            "movie"
          ]
        }
      },
      {
        "_index" : "lib",
        "_type" : "user",
        "_id" : "3",
        "_score" : 0.18232156,
        "_source" : {
          "first_name" : "曹",
          "last_name" : "輝3",
          "age" : 24,
          "about" : "I like LULU",
          "interest" : [
            "movie"
          ]
        }
      },
      {
        "_index" : "lib",
        "_type" : "user",
        "_id" : "1",
        "_score" : 0.18232156,
        "_source" : {
          "first_name" : "曹",
          "last_name" : "輝1",
          "age" : 24,
          "about" : "I like LULU",
          "interest" : [
            "movie"
          ]
        }
      },
      {
        "_index" : "lib",
        "_type" : "user",
        "_id" : "ZTLbRG4BO86YojzOMVx8",
        "_score" : 0.18232156,
        "_source" : {
          "first_name" : "楊",
          "last_name" : "璐",
          "age" : 23,
          "about" : "I like Caohui",
          "interest" : [
            "movie"
          ]
        }
      }
    ]
  }
}

按照某個屬性排序的查詢

# q參數表示搜索的條件,:前面表示搜索的字段,:後面表示關鍵字
# 按照age的降序查詢about熟悉中帶有like的文檔
GET /lib/user/_search?q=about:like&sort=age:desc

6.6.1 term和terms查詢

  • term查詢,將查詢條件放入term字段。

    GET /lib/user/_search
    {
      "query":{
        "term":{"name":"cao"}
      }
    }
    

    結果是lib索引中所有name中帶有cao的文檔,需要注意的是,這裏的term中只能有一個查詢條件(雖然是是{}表示的,但是不能寫成{“name”:“cao”,“age”:25})。

    查詢結果如下

    {
      "took" : 0,
      "timed_out" : false,
      "_shards" : {
        "total" : 3,
        "successful" : 3,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 1,
          "relation" : "eq"
        },
        "max_score" : 0.2876821,
        "hits" : [
          {
            "_index" : "lib",
            "_type" : "user",
            "_id" : "10",
            "_score" : 0.2876821,
            "_source" : {
              "name" : "cao hui",
              "age" : 24,
              "address" : {
                "province" : "ZheJiang",
                "city" : "HangZhou"
              }
            }
          }
        ]
      }
    }
    
  • terms查詢,和term的不同點就是查詢條件的值可以有多個,不同值之間是"或"的關係。

    GET /lib/user/_search
    {
      "query":{
        "terms":{
          "name":["cao"]
        }
      }
    }
    

    和term一樣,terms裏面的屬性也只能有一個,但是中括號裏面可以有多個值。

  • from和size

    from和size是查詢的限制文檔個數,顧名思義

    
    GET /lib/user/_search
    { 
      "from":0,
      "size":10,
      "query":{
        "terms":{
          "name":["cao"]
        }
      }
    }
    
  • version, 查詢中,version設置爲true,則查詢結果中出現文檔的版本號。

    GET /lib/user/_search
    { 
      "version":"true",
      "from":0,
      "size":10,
      "query":{
        "terms":{
          "name":["cao"]
        }
      }
    }
    
  • match查詢

    match查詢是帶有分詞器的查詢。下面的查詢可以查出name屬性中帶有cao和lu的所有文檔。

    # 帶有分詞器的查詢
    GET /lib/user/_search
    { 
      "query":{
        "match":{
          "name":"cao,lu"
        }
      }
    }
    

    下面是查詢所有文檔。

    # 查詢所有文檔
    GET /lib/user/_search
    { 
      "query":{
        "match_all":{
        }
      }
    }
    

    多項匹配,下面的查詢可以查詢出所有name或about字段帶cao的所有文檔。

    # multi_match,fields包含的字段當中,都會查詢出來
    
    GET /lib/user/_search
    { 
      "query":{
        "multi_match":{
          "query":"cao",
          "fields":["name","about"]
        }
      }
    }
    
    

    短語匹配,查詢某屬性帶有某短語的所有文檔。

    # match_phrase ,必須含有完全一樣的短語
    
    GET /lib/user/_search
    { 
      "query":{
        "match_phrase":{
          "name":"cao hui"
        }
      }
    }
    

    通過_source字段可以指明查出來的結果需要哪些字段,下面表示只需要name和age字段。

    # 通過_source 指明返回哪些字段
    
    GET /lib/user/_search
    { 
      "_source":["name", "age"],
      "query":{
        "match_phrase":{
          "name":"cao hui"
        }
      }
    }
    

6.6.2 利用ik分詞器進行中文分詞查詢

首先創建一個lib,使用的分詞器是中文分詞器。

# 新建一個lib,其中text類型使用ik_max_word中文分詞器。
PUT /mylib
{
  "settings": {
    "number_of_replicas": 0,
    "number_of_shards": 3
  },
  "mappings": {
    "properties": {
      "name":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "address":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "age":{
        "type": "integer"
      },
      "interests":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "birthday":{
        "type": "date"
      }
    }
  }
}

然後向其中增加一些帶有中文的數據。

PUT mylib/_doc/1
{
  "name":"趙六",
  "address":"黑龍江省鐵嶺",
  "age":50,
  "birthday":"1970-12-12",
  "interests":"喜歡喝酒、鍛鍊、說相聲"
}



PUT mylib/_doc/2
{
  "name":"趙明",
  "address":"北京海淀區清河",
  "age":20,
  "birthday":"1998-10-12",
  "interests":"喜歡喝酒,鍛鍊,唱歌"
}

PUT mylib/_doc/3
{
  "name":"lisi",
  "address":"北京海淀區清河",
  "age":23,
  "birthday":"1998-10-12",
  "interests":"喜歡喝酒,鍛鍊,唱歌"
}

PUT mylib/_doc/4
{
  "name":"王五",
  "address":"北京海淀區清河",
  "age":26,
  "birthday":"1995-10-12",
  "interests":"喜歡編程、聽音樂、旅遊"
}

PUT mylib/_doc/5
{
  "name":"張三",
  "address":"北京海淀區清河",
  "age":29,
  "birthday":"1988-10-12",
  "interests":"喜歡攝影、聽音樂、跳舞"
}

然後就可以查詢中文了。

  • 前綴短語。

    GET mylib/_doc/_search
    {
      "query":{
        "match_phrase_prefix":{
          "interests":"喜歡"
        }
      }
    }
    
  • 範圍查詢,默認是左閉右開區間。

    GET mylib/_doc/_search
    {
      "query":{
        "range":{
          "age":{
            "from":20,
            "to":25,
            "include_lower":"true",
            "include_upper":"false"
          }
        }
      }
    }
    
  • 模糊查詢, 查詢某字段中帶有某些子的文檔。

    GET mylib/_doc/_search
    { 
      "query":{
        "fuzzy":{
          "interests":"鍛鍊"
        }
      }
    }
    
  • 通配符*和?的查詢

    GET mylib/_doc/_search
    { 
      "query":{
        "wildcard":{
          "interests":"*鍛練*"
        }
      }
    }
    

6.6.3 過濾查詢,條件查詢

ES的過濾查詢是根據關鍵字filter,可以根據條件過濾文檔,如下所示。

#找到age是20的文檔
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
        "term":{
          "age":"20"
        }
      }
    }
  }
}


#找到age是20和23的文檔
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
        "terms":{
          "age":[20,23]
        }
      }
    }
  }
}

ES的條件查詢是通過關鍵字shouldmustmust_not來實現的。

  • should表示,“應該含有什麼”,如果沒有must,則查詢結果以should指定的值爲準。但是如果有must,should不起作用。
  • must,必須包含的
  • must_not,必須不包含的

如下所示

#bool查詢, should,must,must_not

#查詢age是20或23,且name不是caohui的文檔
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "should":[
        {
          "term":{
            "age":20
          }
        },{
          "term":{
            "age":23
          }
        }
      ],
      "must_not":
       {
         "term":{
            "name":"caohui"
          } 
        }
    }
  }
}

#查詢interests包含喝酒且name不是曹輝的文檔
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "must_not":
       {
         "term":{
            "name":"caohui"
          } 
        },
      "must":[
        {
          "terms":{
              "interests":["喝酒"]
          }
        }
      ]
    }
  }
}

範圍過濾,ES通過gt 表示 >, lt 表示 < , gte 表示 >= , lte 表示 <=, exists表示存在。例子如下。

#查詢  20 <= age <= 23 的文檔
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
        "range":{
          "age":{
            "gte":20,
            "lte":23
          }
        }
      }
    }
  }
}

# 查詢address屬性不爲null的文檔
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
        "exists":{
          "field":"address"
        }
      }
    }
  }
}

6.6.4 聚合查詢

在ES中存在聚合查詢,例子如下

# 求和,其中 sum_of_age是自己取的名字,字段名,size是0表示結果中不顯示每個文檔。
GET mylib/_doc/_search
{
  "size":0,
  "aggs":{
		
    "sum_of_age":{
      "sum":{
          "field":"age"
      }
    }
  }
}

# 求最大
GET mylib/_doc/_search
{
  "size":0,
  "aggs":{
    "min_of_age":{
      "min":{
          "field":"age"
      }
    }
  }
}

# 求年齡是20或23的年齡最小值
GET mylib/_doc/_search
{
  "query":{
    "bool":{
      "filter":{
          "terms":{
            "age":[20,23]
          }
      }
    }
  },
  "aggs":{
    "max_of_age":{
      "max":{
          "field":"age"
      }
    }
  }
}

# 求年齡的平均值
GET mylib/_doc/_search
{
  "size":0,
  "aggs":{
    "avg_of_age":{
      "avg":{
          "field":"age"
      }
    }
  }
}

# cardinality,相當於數據庫裏的distinct,不重複的元素個數
GET mylib/_doc/_search
{
  "size":0,
  "aggs":{
    "card_of_age":{
      "cardinality":{
          "field":"age"
      }
    }
  }
}

分組

# 分組,按照某字段進行分組
GET mylib/_doc/_search
{
  "size":0,
  "aggs":{
    "group_of_age":{
      "terms":{
          "field":"age"
      }
    }
  }
}

分組的結果是下面的樣子

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 6,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_of_age" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 23,
          "doc_count" : 2
        },
        {
          "key" : 20,
          "doc_count" : 1
        },
        {
          "key" : 26,
          "doc_count" : 1
        },
        {
          "key" : 29,
          "doc_count" : 1
        },
        {
          "key" : 50,
          "doc_count" : 1
        }
      ]
    }
  }
}

下面做一個練習,在興趣爲唱歌的人中,按照年齡進行分組,並且分組按照年齡降序。

GET mylib/_doc/_search
{ 
  "size":0,
  "query":{
    "term":{
      "interests":"唱歌"
    }
  },
  "aggs":{
    "group_of_age":{
      "terms":{
          "field":"age",
          "order":{
            "avg_of_age":"desc"
          }
      },
      "aggs":{
        "avg_of_age":{
          "avg":{
            "field":"age"
          }
        }
      }
    }
  }
}

結果如下所示。

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 3,
    "successful" : 3,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_of_age" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 23,
          "doc_count" : 2,
          "avg_of_age" : {
            "value" : 23.0
          }
        },
        {
          "key" : 20,
          "doc_count" : 1,
          "avg_of_age" : {
            "value" : 20.0
          }
        }
      ]
    }
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章