成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

ElasticSearch常用操作:查詢與聚合篇

[TOC]

專注于為中小企業(yè)提供成都網(wǎng)站建設(shè)、成都網(wǎng)站制作服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)鐵山免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了數(shù)千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。


0 說明

基于es 5.4和es 5.6,列舉的是個人工作中經(jīng)常用到的查詢(只是工作中使用的是Java API),如果需要看完整的,可以參考官方相關(guān)文檔
https://www.elastic.co/guide/en/elasticsearch/reference/5.4/search.html。

1 查詢

先使用一個快速入門來引入,然后后面列出的各種查詢都是用得比較多的(在我的工作環(huán)境是這樣),其它沒怎么用的這里就不列出了。

1.1 快速入門

1.1.1 查詢?nèi)?/h5>
GET index/type/_search
{
    "query":{
        "match_all":{}
    }
}

GET index/type/_search
1.1.2 分頁(以term為例)
GET index/type/_search
{
    "from":0,
    "size":100,
    "query":{
        "term":{
            "area":"GuangZhou"
        }
    }
}
1.1.3 包含指定字段(以term為例)
GET index/type/_search
{
    "_source":["hobby", "name"],
    "query":{
        "term":{
            "area":"GuangZhou"
        }
    }
}
1.1.4 排序(以term為例)

單個字段排序:

GET index/type/_search
{
    "query":{
        "term":{
            "area":"GuangZhou"
        }
    },
    "sort":[
        {"user_id":{"order":"asc"}},
        {"salary":{"order":"desc"}}
    ]
}

1.2 全文查詢

查詢字段會被索引和分析,在執(zhí)行之前將每個字段的分詞器(或搜索分詞器)應(yīng)用于查詢字符串。

1.2.1 match query
{
  "query": {
    "match": {
      "content": {
        "query": "里皮恒大",
        "operator": "and"
      }
    }
  }
}

operator默認(rèn)是or,也就是說,“里皮恒大”被分詞為“里皮”和“恒大”,只要content中出現(xiàn)兩個之一,都會搜索到;設(shè)置為and之后,只有同時出現(xiàn)都會被搜索到。

1.2.2 match_phrase query

文檔同時滿足下面兩個條件才會被搜索到:

  • (1)分詞后所有詞項都要出現(xiàn)在該字段中
  • (2)字段中的詞項順序要一致
{
  "query": {
    "match_phrase": {
      "content": "里皮恒大"
    }
  }
}

1.3 詞項查詢

詞項搜索時對倒排索引中存儲的詞項進行精確匹配,詞項級別的查詢通過用于結(jié)構(gòu)化數(shù)據(jù),如數(shù)字、日期和枚舉類型。

1.3.1 term query
{
  "query": {
    "term": {
      "postdate": "2015-12-10 00:41:00"
    }
  }
}
1.3.2 terms query

term的升級版,如上面查詢的postdate字段,可以設(shè)置多個。

{
  "query": {
    "terms": {
      "postdate": [
        "2015-12-10 00:41:00",
        "2016-02-01 01:39:00"
      ]
    }
  }
}

因為term是精確匹配,所以不要問,[]中的關(guān)系怎么設(shè)置and?這怎么可能,既然是精確匹配,一個字段也不可能有兩個不同的值。

1.3.3 range query

匹配某一范圍內(nèi)的數(shù)據(jù)型、日期類型或者字符串型字段的文檔,注意只能查詢一個字段,不能作用在多個字段上。

數(shù)值:

{
  "query": {
    "range": {
      "reply": {
        "gte": 245,
        "lte": 250
      }
    }
  }
}

支持的操作符如下:

gt:大于,gte:大于等于,lt:小于,lte:小于等于

日期:

{
  "query": {
    "range": {
      "postdate": {
        "gte": "2016-09-01 00:00:00",
        "lte": "2016-09-30 23:59:59",
        "format": "yyyy-MM-dd HH:mm:ss"
      }
    }
  }
}

format不加也行,如果寫的時間格式正確。

1.3.4 exists query

返回對應(yīng)字段中至少有一個非空值的文檔,也就是說,該字段有值(待會會說明這個概念)。

{
  "query": {
    "exists": {
      "field": "user"
    }
  }
}

參考《從Lucene到Elasticsearch:全文檢索實戰(zhàn)》中的說明。

以下文檔會匹配上面的查詢:

文檔說明
{"user":"jane"} 有user字段,且不為空
{"user":""} 有user字段,值為空字符串
{"user":"-"} 有user字段,值不為空
{"user":["jane"]} 有user字段,值不為空
{"user":["jane",null]} 有user字段,至少一個值不為空即可

下面的文檔不會被匹配:

文檔說明
{"user":null} 雖然有user字段,但是值為空
{"user":[]} 雖然有user字段,但是值為空
{"user":[null]} 雖然有user字段,但是值為空
{"foo":"bar"} 沒有user字段
1.3.5 ids query

查詢具有指定id的文檔。

{
  "query": {
    "ids": {
      "type": "news",
      "values": "2101"
    }
  }
}

類型是可選的,也可以以數(shù)據(jù)的方式指定多個id。

{
  "query": {
    "ids": {
      "values": [
        "2101",
        "2301"
      ]
    }
  }
}

1.4 復(fù)合查詢

1.4.1 bool query

因為工作中接觸到關(guān)于es是做聚合、統(tǒng)計、分類的項目,經(jīng)常要做各種復(fù)雜的多條件查詢,所以實際上,bool query用得非常多,因為查詢條件個數(shù)不定,所以處理的邏輯思路時,外層用一個大的bool query來進行承載。(當(dāng)然,項目中是使用其Java API)

bool query可以組合任意多個簡單查詢,各個簡單查詢之間的邏輯表示如下:

屬性說明
must 文檔必須匹配must選項下的查詢條件,相當(dāng)于邏輯運算的AND
should 文檔可以匹配should選項下的查詢條件,也可以不匹配,相當(dāng)于邏輯運算的OR
must_not 與must相反,匹配該選項下的查詢條件的文檔不會被返回
filter 和must一樣,匹配filter選項下的查詢條件的文檔才會被返回,但是filter不評分,只起到過濾功能

一個例子如下:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "content": "里皮"
        }
      },
      "must_not": {
        "match": {
          "content": "中超"
        }
      }
    }
  }
}

需要注意的是,同一個bool下,只能有一個must、must_not、should和filter。

如果希望有多個must時,比如希望同時匹配"里皮"和"中超",但是又故意分開這兩個關(guān)鍵詞(因為事實上,一個must,然后使用match,并且operator為and就可以達到目的),怎么操作?注意must下使用數(shù)組,然后里面多個match對象就可以了:

{
  "size": 1,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "里皮"
          }
        },
        {
          "match": {
            "content": "恒大"
          }
        }
      ]
    }
  },
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ]
}

當(dāng)然must下的數(shù)組也可以是多個bool查詢條件,以進行更加復(fù)雜的查詢。

上面的查詢等價于:

{
  "query": {
    "bool": {
      "must": {
        "match": {
          "content": {
            "query": "里皮恒大",
            "operator": "and"
          }
        }
      }
    }
  },
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ]
}

1.5 嵌套查詢

先添加下面一個索引:

PUT /my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "user":{
          "type": "nested",
          "properties": {
            "first":{"type":"keyword"},
            "last":{"type":"keyword"}
          }
        },
        "group":{
          "type": "keyword"
        }
      }
    }
  }
}

添加數(shù)據(jù):

PUT my_index/my_type/1
{
  "group":"GuangZhou",
  "user":[
    {
      "first":"John",
      "last":"Smith"
    },
    {
      "first":"Alice",
      "last":"White"
    }
  ]
}

PUT my_index/my_type/2
{
  "group":"QingYuan",
  "user":[
    {
      "first":"Li",
      "last":"Wang"
    },
    {
      "first":"Yonghao",
      "last":"Ye"
    }
  ]
}

查詢:

較簡單的查詢:

{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "term": {
          "user.first": "John"
        }
      }
    }
  }
}

較復(fù)雜的查詢:

{
  "query": {
    "bool": {
      "must": [
        {"nested": {
          "path": "user",
          "query": {
            "term": {
              "user.first": {
                "value": "Li"
              }
            }
          }
        }},
        {
          "nested": {
            "path": "user",
            "query": {
              "term": {
                "user.last": {
                  "value": "Wang"
                }
              }
            }
          }
        }
      ]
    }
  }
}

1.6 補充:數(shù)組查詢與測試

添加一個索引:

PUT my_index2
{
  "mappings": {
    "my_type2":{
      "properties": {
        "message":{
          "type": "text"
        },
        "keywords":{
          "type": "keyword"
        }
      }
    }
  }
}

添加數(shù)據(jù):

PUT /my_index2/my_type/1
{
  "message":"keywords test1",
  "keywords":["美女","動漫","電影"]
}

PUT /my_index2/my_type/2
{
  "message":"keywords test2",
  "keywords":["電影","美妝","廣告"]
}

搜索:

{
  "query": {
    "term": {
      "keywords": "廣告"
    }
  }
}

Note1:注意設(shè)置字段類型時,keywords設(shè)置為keyword,所以使用term查詢可以精確匹配,但設(shè)置為text,則不一定——如果有添加分詞器,則可以搜索到;如果沒有,而是使用默認(rèn)的分詞器,只是將其分為一個一個的字,就不會被搜索到。這點尤其需要注意到。

Note2:對于數(shù)組字段,也是可以做桶聚合的,做桶聚合的時候,其每一個值都會作為一個值去進行分組,而不是整個數(shù)組進行分組,可以使用上面的進行測試,不過需要注意的是,其字段類型不能為text,否則聚合會失敗。

Note3:所以根據(jù)上面的提示,一般純數(shù)組比較適合存放標(biāo)簽類的數(shù)據(jù),就像上面的案例一樣,同時字段類型設(shè)置為keyword,而不是text,搜索時進行精確匹配就好了。

1.7 滾動查詢scroll

如果一次性要查出來比如10萬條數(shù)據(jù),那么性能會很差,此時一般會采取用scoll滾動查詢,一批一批的查,直到所有數(shù)據(jù)都查詢完處理完(es返回的scrollId,可以理解為是es進行此次查詢的操作句柄標(biāo)識,每發(fā)送一次該scrollId,es都會操作一次,或者說循環(huán)一次,直到時間窗口到期)。

使用scoll滾動搜索,可以先搜索一批數(shù)據(jù),然后下次再搜索一批數(shù)據(jù),以此類推,直到搜索出全部的數(shù)據(jù)來,scoll搜索會在第一次搜索的時候,保存一個當(dāng)時的視圖快照,之后只會基于該舊的視圖快照提供數(shù)據(jù)搜索,如果這個期間數(shù)據(jù)變更,是不會讓用戶看到的,每次發(fā)送scroll請求,我們還需要指定一個scoll參數(shù),指定一個時間窗口,每次搜索請求只要在這個時間窗口內(nèi)能完成就可以了(也就是說,該scrollId只在這個時間窗口內(nèi)有效,視圖快照也是)。

GET spnews/news/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 10,
  "_source": ["id"]
}

GET _search/scroll
{
  "scroll":"1m",
  "scroll_id":"DnF1ZXJ5VGhlbkZldGNoAwAAAAAAADShFmpBMjJJY2F2U242RFU5UlAzUzA4MWcAAAAAAAA0oBZqQTIySWNhdlNuNkRVOVJQM1MwODFnAAAAAAAANJ8WakEyMkljYXZTbjZEVTlSUDNTMDgxZw=="
}

2 聚合

2.1 指標(biāo)聚合

相當(dāng)于MySQL的聚合函數(shù)。

max
{
  "size": 0,
  "aggs": {
    "max_id": {
      "max": {
        "field": "id"
      }
    }
  }
}

size不設(shè)置為0,除了返回聚合結(jié)果外,還會返回其它所有的數(shù)據(jù)。

min
{
  "size": 0,
  "aggs": {
    "min_id": {
      "min": {
        "field": "id"
      }
    }
  }
}
avg
{
  "size": 0,
  "aggs": {
    "avg_id": {
      "avg": {
        "field": "id"
      }
    }
  }
}
sum
{
  "size": 0,
  "aggs": {
    "sum_id": {
      "sum": {
        "field": "id"
      }
    }
  }
}
stats
{
  "size": 0,
  "aggs": {
    "stats_id": {
      "stats": {
        "field": "id"
      }
    }
  }
}

2.2 桶聚合

相當(dāng)于MySQL的group by操作,所以不要嘗試對es中text的字段進行桶聚合,否則會失敗。

Terms

相當(dāng)于分組查詢,根據(jù)字段做聚合。

{
  "size": 0,
  "aggs": {
    "per_count": {
      "terms": {
        "size":100,
        "field": "vtype",
        "min_doc_count":1
      }
    }
  }
}

在桶聚合的過程中還可以進行指標(biāo)聚合,相當(dāng)于mysql做group by之后,再做各種max、min、avg、sum、stats之類的:

{
  "size": 0,
  "aggs": {
    "per_count": {
      "terms": {
        "field": "vtype"
      },
      "aggs": {
        "stats_follower": {
          "stats": {
            "field": "realFollowerCount"
          }
        }
      }
    }
  }
}
Filter

相當(dāng)于是MySQL根據(jù)where條件過濾出結(jié)果,然后再做各種max、min、avg、sum、stats操作。

{
  "size": 0,
  "aggs": {
    "gender_1_follower": {
      "filter": {
        "term": {
          "gender": 1
        }
      },
      "aggs": {
        "stats_follower": {
          "stats": {
            "field": "realFollowerCount"
          }
        }
      }
    }
  }
}

上面的聚合操作相當(dāng)于是:查詢gender為1的各個指標(biāo)。

Filters

在Filter的基礎(chǔ)上,可以查詢多個字段各自獨立的各個指標(biāo),即對每個查詢結(jié)果分別做指標(biāo)聚合。

{
  "size": 0,
  "aggs": {
    "gender_1_2_follower": {
      "filters": {
        "filters": [
          {
            "term": {
              "gender": 1
            }
          },
          {
            "term": {
              "gender": 2
            }
          }
        ]
      },
      "aggs": {
        "stats_follower": {
          "stats": {
            "field": "realFollowerCount"
          }
        }
      }
    }
  }
}
Range
{
  "size": 0,
  "aggs": {
    "follower_ranges": {
      "range": {
        "field": "realFollowerCount",
        "ranges": [
          {
            "to": 500
          },
          {
            "from": 500,
            "to": 1000
          },
          {
            "from": 1000,
            "to": 1500
          },
          {
            "from": "1500",
            "to": 2000
          },
          {
            "from": 2000
          }
        ]
      }
    }
  }
}

to:小于,from:大于等于

Date Range

跟上面一個類似的,其實只是字段為日期類型的,然后范圍值也是日期。

Date Histogram Aggregation

這個功能十分有用,可以根據(jù)年月日來對數(shù)據(jù)進行分類。
索引下面的文檔:

DELETE my_blog

PUT my_blog
{
  "mappings": {
    "article":{
      "properties": {
        "title":{"type": "text"},
        "postdate":{
          "type": "date"
          , "format": "yyyy-MM-dd HH:mm:ss"
        }
      }
    }
  }
}

PUT my_blog/article/1
{
  "title":"Elasticsearch in Action",
  "postdate":"2014-09-23 23:34:12"
}

PUT my_blog/article/2
{
  "title":"Spark in Action",
  "postdate":"2015-09-13 14:12:22"
}

PUT my_blog/article/3
{
  "title":"Hadoop in Action",
  "postdate":"2016-08-23 23:12:22"
}

按年對數(shù)據(jù)進行聚合:

GET my_blog/article/_search
{
  "size": 0, 
  "aggs": {
    "agg_year": {
      "date_histogram": {
        "field": "postdate",
        "interval": "year",
        "order": {
          "_key": "asc"
        }
      }
    }
  }
}

{
  "took": 18,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "agg_year": {
      "buckets": [
        {
          "key_as_string": "2014-01-01 00:00:00",
          "key": 1388534400000,
          "doc_count": 1
        },
        {
          "key_as_string": "2015-01-01 00:00:00",
          "key": 1420070400000,
          "doc_count": 1
        },
        {
          "key_as_string": "2016-01-01 00:00:00",
          "key": 1451606400000,
          "doc_count": 1
        }
      ]
    }
  }
}

按月對數(shù)據(jù)進行聚合:

GET my_blog/article/_search
{
  "size": 0, 
  "aggs": {
    "agg_year": {
      "date_histogram": {
        "field": "postdate",
        "interval": "month",
        "order": {
          "_key": "asc"
        }
      }
    }
  }
}

這樣聚合的話,包含的年份的每一個月的數(shù)據(jù)都會被分類,不管其是否包含文檔。

按日對數(shù)據(jù)進行聚合:

GET my_blog/article/_search
{
  "size": 0, 
  "aggs": {
    "agg_year": {
      "date_histogram": {
        "field": "postdate",
        "interval": "day",
        "order": {
          "_key": "asc"
        }
      }
    }
  }
}

這樣聚合的話,包含的年份的每一個月的每一天的數(shù)據(jù)都會被分類,不管其是否包含文檔。

本文標(biāo)題:ElasticSearch常用操作:查詢與聚合篇
文章轉(zhuǎn)載:http://jinyejixie.com/article28/pdcjcp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、網(wǎng)站策劃、品牌網(wǎng)站制作、服務(wù)器托管、定制開發(fā)、手機網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司
小金县| 白水县| 浦北县| 手机| 沈阳市| 东宁县| 翼城县| 翼城县| 喀喇| 韩城市| 高台县| 内乡县| 枞阳县| 墨玉县| 仲巴县| 锦州市| 施秉县| 池州市| 武安市| 玉环县| 静海县| 汶上县| 剑川县| 武城县| 九寨沟县| 嘉祥县| 务川| 漳州市| 霍山县| 随州市| 临邑县| 胶州市| 原阳县| 东阿县| 盐城市| 扬州市| 和硕县| 博乐市| 大冶市| 乡宁县| 兴仁县|