ELK技術棧中的那些查詢語法

ES-基本概念

  • 詞項: 全部文檔中出現的不重複個體
  • 分片: 底層工做單元,保存所有數據中的一部分,能搜索任意一個節點上的資源(文檔會被存儲和索引到分片內)。分爲主分片和副本分片,索引內的任意一個文檔都歸屬於主分片,副本分片是主分片的拷貝,提供讀服務,副本分片和主分片不會被分到同一個節點
  • Document: 根對象,能被indexed的基本信息單元,用JSON表示,ID惟一,不可修改,只能替換
  • 文檔元數據html

    1. _Index 索引。類似document的集合,標明文檔存放的位置
    2. _type 數據子分區。同一索引下的數據邏輯分區,一個索引能夠有多個類型
    3. _id 與 _index,_type一塊兒惟一肯定一個文檔
    4. _version 保證相互衝突的變動不會致使數據丟失。ES使用樂觀併發控制,默認不阻塞併發請求,若是請求版本號不對,返回錯誤狀態碼
  • Shards: 索引被切分存儲的片斷
  • Replication: 索引shards的拷貝
  • _score:正浮點數,表示相關性,評分越高,相關性越高
  • 倒排索引:文檔中全部不重複詞的列表構成,其中每一個詞有一個包含它的文檔列表,只能搜索到索引中存在的詞條

ES-命令行使用

集羣操做

查詢集羣的名字java

⇒  curl -XGET 'http://localhost:9200'

查詢集羣的健康情況git

⇒  curl -XGET 'http://localhost:9200/_cluster/health?format=yaml'

status字段說明:github

  1. green 一切正常
  2. yellow replicas沒有分配[多是隻有單個節點],集羣正常
  3. red 某些數據取不到

format=yaml指定使用yaml格式輸出,方便查看web

索引操做

獲取集羣的全部索引數據庫

⇒  curl -XGET 'http://localhost:9200/_cat/indices'

索引的字段apache

⇒  curl -XGET 'http://localhost:9200/mytest/_mapping?format=yaml'

結果併發

mytest:
 mappings:
   external:
  properties:
    addre:
      type: "string"
    name:
      type: "string"
它相似於數據庫的schema,描述文檔可能具備的字段或屬性、每一個字段的數據類型。

字段對於非string類型,通常只須要設置type。string域兩重要屬性 index analyzerapp

indexcurl

1. analyzed 全文索引這個域。首先分析字符串,而後索引

    2. not_analyzed 精確索引 ,不分析            

    3. no 此域不會被搜索
analyzer
將文本分紅四核倒排索引的獨立詞條,後將詞條統一化提升可搜索性
動態映射: 文檔中出現以前從未遇到過的字段,動態肯定數據類型,並自動把新的字段添加到類型映射

新建索引

⇒  curl -XPUT 'localhost:9200/mytest'

刪除索引

⇒  curl -XDELETE 'localhost:9200/mytest?format=yaml'

數據查詢

插入單條數據

⇒  curl -XPUT 'localhost:9200/mytest/external/1?format=yaml' -d '
quote> { "name":"paxi"}'

查詢單條數據

⇒  curl -XGET 'localhost:9200/mytest/external/1?format=yaml'

刪除單條數據

curl -XDELETE 'localhost:9200/mytest/external/3?format=yaml'

存儲的文本分析

curl -XGET 'localhost:9200/_analyze?format=yaml' -d '
{"papa xixi write"}'

結果爲

tokens:
- token: "papa"
  start_offset: 3
  end_offset: 7
  type: "<ALPHANUM>"
  position: 1
- token: "xixi"
  start_offset: 8
  end_offset: 12
  type: "<ALPHANUM>"
  position: 2
- token: "write"
  start_offset: 13
  end_offset: 18
  type: "<ALPHANUM>"
  position: 3
token 表示實際存儲的詞條,position表示詞條在原始文本中的位置。

能夠看出完整的文本會被切割存儲成不一樣的詞條

不返回元數據

curl -XGET 'localhost:9200/mytest/_search?filter_path=hits.hits._source&format=yaml' -d '
{ "query":{"match":{"name":"papa xixi write"}}}'
低版本沒法生效

只返回部分字段

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"match":{"name":"papa xixi write"}},"_source":["name"]}'
低版本無效,能夠用通配符

match查詢

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"match":{"name":"papa xixi write"}}}'
查詢匹配的結果以下
hits:
  - _index: "mytest"
    _type: "external"
    _id: "11"
    _score: 0.6532502
    _source:
      name: "papa xixi write"
  - _index: "mytest"
    _type: "external"
    _id: "4"
    _score: 0.22545706
    _source:
      name: "papa xixi"
  - _index: "mytest"
    _type: "external"
    _id: "2"
    _score: 0.12845722
    _source:
      name: "papa"
  - _index: "mytest"
    _type: "external"
    _id: "10"
    _score: 0.021688733
    _source:
      name: "xixi"
從查詢結果,它獲取到了全部包含 papa 、 xixi和write 的詞,至關於將原來的詞拆開,而後兩個單詞作了 OR 操做,若是要所有匹配,可使用AND操做
curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"match":{"name":{"query":"papa xixi write","operator":"and"}}}}'
---
  hits:
  total: 1
  max_score: 0.6532502
  hits:
  - _index: "mytest"
    _type: "external"
    _id: "11"
    _score: 0.6532502
    _source:
      name: "papa xixi write"
若是隻是想提升精度
curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"match":{"name":{"query":"papa xixi write","minimum_should_match":"75%"}}}}'
---
hits:
  total: 2
  max_score: 0.6532502
  hits:
  - _index: "mytest"
    _type: "external"
    _id: "11"
    _score: 0.6532502
    _source:
      name: "papa xixi write"
  - _index: "mytest"
    _type: "external"
    _id: "4"
    _score: 0.22545706
    _source:
      name: "papa xixi"

term查詢

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"term":{"name":"papa xixi write"}}}'
它的結果是什麼也沒有查到
total: 0
  max_score: null
  hits: []
換用查詢語句
curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"term":{"name":"papa"}}}'
結果爲
hits:
  - _index: "mytest"
    _type: "external"
    _id: "2"
    _score: 1.0
    _source:
      name: "papa"
  - _index: "mytest"
    _type: "external"
    _id: "4"
    _score: 0.37158427
    _source:
      name: "papa xixi"
  - _index: "mytest"
    _type: "external"
    _id: "11"
    _score: 0.2972674
    _source:
      name: "papa xixi write"

match 和 term的區別

match 若是在全文字段上查詢,會使用正確的分析器分析查詢字符串;若是精確值字段使用,會精確匹配。 term精確匹配,只要包含了對應的文本就能夠,不對文本分析(not_analyzed文本會精確匹配,terms 多個值只要有一個匹配就匹配);

從"papa xixi write"的存儲文本分析來看,它自己會被切割成不一樣的詞條,因此用 term查詢"papa xixi write",沒法獲取到結果,可是match確可以匹配

filter使用

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"filtered":{"filter":{"range":{"name":{"gt":"w"}}}}}}'

或者

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"constant_score":{"filter":{"range":{"name":{"gt":"w"}}}}}}'

驗證語法是否正確

⇒  curl -XGET 'localhost:9200/_validate/query?explain&format=yaml' -d '{ "query":{{"filter":{"range":{"name":{"gt":"w"}}}}}'
---
valid: false
//緣由省略

bool使用

使用term查詢

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ "query":{"term":{"addre":"beijing"}}}'
結果爲
hits:
  - _index: "mytest"
    _type: "external"
    _id: "5"
    _score: 0.30685282
    _source:
      addre: "beijing"
  - _index: "mytest"
    _type: "external"
    _id: "6"
    _score: 0.30685282
    _source:
      addre: "beijing"
      name: "px"

轉換爲bool查詢,結果同樣

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ query:{bool:{must:{match:{addre:"beijing"}}}}}'

若是隻想要最後一條

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ query:{bool:{must:{match:{addre:"beijing"}},must:{match:{name:"px"}}}}}'

想要第一條

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ query:{bool:{must:{match:{addre:"beijing"}},must_not:{match:{name:"px"}}}}}'

都想要

curl -XGET 'localhost:9200/mytest/_search?format=yaml' -d '
{ query:{bool:{must:{match:{addre:"beijing"}},should:{match:{name:"px"}}}}}'
must的意思是當前值必須是有的,must_not必須沒有,should表示數據能夠有也能夠沒有

ES-java查詢

AggregationBuilders.terms:一段時間內,某個字段取值的數量排名前幾的聚合

/ **     @param startTime 開始的時間
     * @param endTime 結束的時間
     * @param termAggName term過濾
     * @param fieldName 要作count的字段
     * @param top 返回的數量
     */
RangeQueryBuilder actionPeriod = QueryBuilders.rangeQuery("myTimeField").gte(startTime).lte(endTime).format("epoch_second");
TermsBuilder termsBuilder = AggregationBuilders.terms(termAggName).field(fieldName).size(top).order(Terms.Order.count(false));
return client.prepareSearch(INDICE).setQuery(actionPeriod).addAggregation(termsBuilder).setSize(0).execute().actionGet();
order(Terms.Order.count(false)):表示降序

size(top):top表示只要排序的數量

prepareSearch(INDICE):INDICE表示索引的名字

setSize(0):表示只要聚合結果

若是須要去掉某些特殊字段取值
client爲構建的ES客戶端

BoolQueryBuilder actionPeriodMustNot = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("myTimeField").gte(startTime).lte(endTime).format("epoch_second")).mustNot(QueryBuilders.termQuery(field, value));
若是是單個字段特定的多個值
//values是個List
BoolQueryBuilder actioPeriodMust = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("myTimeField").gte(startTime).lte(endTime).format("epoch_second")).must(QueryBuilders.termsQuery(field, values));

使用結果

Terms clickCount= sr.getAggregations().get(termAggName);
for (Terms.Bucket term:clickCount.getBuckets()){
  int key = term.getKeyAsNumber().intValue(); //要排序字段的值
  long docCount = term.getDocCount(); //數量
}

date_histogram: 一段時間以內,時間字段按照時間間隔的聚合

BoolQueryBuilder actioPeriodMust = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("myTimeField").gte(startTime).lte(endTime).format("epoch_second"));
DateHistogramBuilder actionInterval = AggregationBuilders.dateHistogram(dateNickName).field("myTimeField").timeZone("Asia/Shanghai");
if (timeInterval<MINUTE){
  actionTimeInterval.interval(DateHistogramInterval.seconds(timeInterval)).format("HH:mm:ss");
}else if (timeInterval<HOUR){
  actionTimeInterval.interval(DateHistogramInterval.minutes(timeInterval / MINUTE)).format("dd HH:mm");
}else if (timeInterval < DAY){
  actionTimeInterval.interval(DateHistogramInterval.hours(timeInterval / HOUR)).format("HH:mm");
}else if (timeInterval < THIRTY_DAY){
  actionTimeInterval.interval(DateHistogramInterval.days(timeInterval / DAY));
}else{
  actionTimeInterval.interval(DateHistogramInterval.MONTH);
}
actionInterval.format("yyyy-MM-dd HH:mm:ssZ");
return client.prepareSearch(INDICE).setQuery(actioPeriodMust).addAggregation(actionInterval).setSize(0).execute().actionGet();
es自己默認設置的時間戳是 UTC形式,在國內要設置TimeZone(「Asia/Shanghai」);

java的SimpleDateFormate會默認獲取虛擬機所在時區的時間戳,因此存時間的時候,最好存與時區無關的時間,再作本地化顯示

使用結果

Histogram histogram=sr.getAggregations().get(dateNickName);
for(Histogram.Bucket entry:histogram.getBuckets()){
  String key = entry.getKeyAsString();//時間間隔
  long count = entry.getDocCount();//數量
}

subAggregation:一段時間內,按照必定的時間間隔,每一個間隔段內字段每一個取值的數量聚合

至關於合併上述兩個場景

BoolQueryBuilder query = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("myTimeField").gte(startTime).lte(endTime).format("epoch_second"))
  .must(QueryBuilders.termsQuery("action", orderValue));
DateHistogramBuilder actionTimeInterval = AggregationBuilders.dateHistogram(dateNickName).field("myTimeField").timeZone("Asia/Shanghai");
actionTimeInterval.subAggregation(AggregationBuilders.terms(termNickName).field("action").size(size));
return client.prepareSearch(INDICE).setQuery(query).addAggregation(actionTimeInterval).setSize(0).execute().actionGet();

使用結果

Histogram hitogram = sr.getAggregations().get(dateAggName);
for (Histogram.Bucket date : hitogram.getBuckets()) {
  String intervalName = date.getKeyAsString();
  long timeIntervalCount = date.getDocCount();
  if (timeIntervalCount != 0) {
    Terms terms = date.getAggregations().get(termAggName);
    for (Terms.Bucket entry : terms.getBuckets()) {
      int key=    entry.getKeyAsNumber().intValue();
      long childCount = entry.getDocCount();
    }
  }
}

分頁獲取數據

BoolQueryBuilder actionPeriodMust = QueryBuilders.boolQuery().must(QueryBuilders.termQuery(key, value)).must(QueryBuilders.rangeQuery("myTimeField").gte(startTime).lte(endTime).format("epoch_second"));
return client.prepareSearch(INDICE).setQuery(actionPeriodMust).addSort(SortBuilders.fieldSort("myTimeField").order(SortOrder.ASC)).setFrom(from).setSize(size).execute().actionGet();

使用

Iterator<SearchHit> iterator = sr.getHits().iterator();
while (iterator.hasNext()) {
  SearchHit next = iterator.next();
  JSONObject jo = JSONObject.parseObject(next.getSourceAsString());
}

AggregationBuilders.cardinality:獲取某個字段的惟一取值數量

BoolQueryBuilder query = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("myTimeField").gte(startTimeInSec*1000).lte(endTimeInSec*1000).format("epoch_millis"));
CardinalityBuilder fieldCardinality = AggregationBuilders.cardinality(cardinalityAggName).field(field);//field 要獲取的字段
return client.prepareSearch(INDICE).setQuery(query).addAggregation(fieldCardinality).execute().actionGet();

使用結果

Cardinality cardinality = sr.getAggregations().get(cardinalityAggName);
long value = cardinality.getValue();

bool查詢

好比想要addr是beijing的,同時必須知足條件:name是 paxi,或者,phoneNumber是 1234567890

BoolQueryBuilder searchIdQuery = QueryBuilders.boolQuery();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
while (kvs.hasNext()){
  Map.Entry<String, String> fieldValue = kvs.next();
  String field=fieldValue.getKey();
  String value=fieldValue.getValue();
  searchIdQuery.should(QueryBuilders.termQuery(field, value));
}
boolQueryBuilder.must(searchIdQuery);
boolQueryBuilder.must(QueryBuilders.termsQuery(key, values));
return client.prepareSearch(INDICE).setQuery(boolQueryBuilder).execute().actionGet();

LogStash

./bin/logstash -f conf/test.conf 啓動方式

  • [] 字段引用,將字段名放到裏面便可。 例如: 獲取精度 geoip[0]
  • a => true 數據類型,前面表明數據的字段名,後面是值,當前爲bool
  • stdin 中 type用來標記事件類型,tags由具體插件添加、刪除
  • start_position: logstash讀取文件的初始位置,默認使用結束位置

grok表達式語法

  1. 完整語法: %{PATTERN_NAME:capture_name:data_type}
  2. 寫表達式若是沒有徹底匹配那麼會匹配失敗
  3. 同樣的字符串直接寫對應字符便可,但願解析的用%{}包裹
  4. (?<param1>w+) 表示匹配 單詞 一次或屢次並將結果存儲在 param1裏面
  5. pattern_dir 指定grok表達式存儲的位置,match直接引用
  6. 正則寫到想要匹配的位置便可

附錄

grok 表達式驗證地址 官方grok內置正則 正則語法

Kibana查詢

kibana框中的查詢可使用LUCENE查詢語法或者是ES的查詢語句

Field

查詢指定的字段不然使用默認字段

好比 index包含兩個字段 title , text ;text是默認字段

title:」hello world」 AND text:to 和 title:」hello world」 AND to 等效

title: hello world 查詢的則是 title爲hello的字段 text爲world的字段

wildcard

te?t 匹配 text test ;表示任意一個字符

test* 匹配 test tests tester;表示0到多個字符

?和 * 不能用在第一個位置

Fuzzy

roam~ 匹配 foam和roams 基於 Levenshtein Distance,波浪線添加在末尾。從1.9版本開始能夠追加數字表明類似度,越接近1類似度越高,好比 roam~0.8,默認是0.5

Proximity

「jakarta apache」~10 匹配從jakarta到apache中間隔10個單詞

Range

mode_date:[20020101 TO 20030101] 匹配時間在20020101到20030101之間,包括20020101和20030101

title:{Aida TO Carmen} 匹配Aida 到 Carmen之間,不包括Aida和Carmen

「[」表示包含 「{」表示不包含

AND(+) OR NOT(-)

關鍵字要大寫

(jakarta OR apache) AND website 組合查詢 包含 website 和 jakarta/apache

逃逸字符

\(1\+1\)\:2

使用ES查詢語法

將ES命令中的 -d 後面的參數加入便可;好比curl查詢爲

curl -XGET 'localhost:9200/_search?format=yaml' -d '
{ "query":{"term":{"addre":"beijing"}}}'

命令行下輸入爲:{ "query":{"term":{"addre":"beijing"}}}

附錄

Lucene 語法

相關文章
相關標籤/搜索