使用 https://github.com/taowen/es-monitor 可以用 SQL 進行 elasticsearch 的查詢。前面我們瞭解到在聚合之前可以做很多種變換,然後把變換之後的key再去分桶。這種變換的終極形式就是自定義表示式,當然自定義表示式的效率也是最低的。
GROUP BY ipo_year % AS ipo_year_rem
SQL
$ cat << EOF | ./es_query.py http://127.0.0.1:9200
SELECT ipo_year_rem, COUNT(*) FROM symbol GROUP BY ipo_year % 5 AS ipo_year_rem
EOF
{"COUNT(*)": 715, "ipo_year_rem": 4.0}
{"COUNT(*)": 677, "ipo_year_rem": 0.0}
{"COUNT(*)": 537, "ipo_year_rem": 2.0}
{"COUNT(*)": 523, "ipo_year_rem": 3.0}
{"COUNT(*)": 446, "ipo_year_rem": 1.0}
Elasticsearch
{
"aggs": {
"ipo_year_rem": {
"terms": {
"field": "ipo_year",
"size": 0,
"script": {
"lang": "expression",
"inline": "_value % 5"
}
},
"aggs": {}
}
},
"size": 0
}
{
"hits": {
"hits": [],
"total": 6714,
"max_score": 0.0
},
"_shards": {
"successful": 1,
"failed": 0,
"total": 1
},
"took": 2,
"aggregations": {
"ipo_year_rem": {
"buckets": [
{
"key": 4.0,
"doc_count": 715
},
{
"key": 0.0,
"doc_count": 677
},
{
"key": 2.0,
"doc_count": 537
},
{
"key": 3.0,
"doc_count": 523
},
{
"key": 1.0,
"doc_count": 446
}
],
"sum_other_doc_count": 0,
"doc_count_error_upper_bound": 0
}
},
"timed_out": false
}
Profile
[
{
"query": [
{
"query_type": "MatchAllDocsQuery",
"lucene": "*:*",
"time": "1.046876000ms",
"breakdown": {
"score": 0,
"create_weight": 16550,
"next_doc": 835828,
"match": 0,
"build_scorer": 194498,
"advance": 0
}
}
],
"rewrite_time": 8693,
"collector": [
{
"name": "MultiCollector",
"reason": "search_multi",
"time": "2.994827000ms",
"children": [
{
"name": "TotalHitCountCollector",
"reason": "search_count",
"time": "0.3955230000ms"
},
{
"name": "DoubleTermsAggregator: [ipo_year_rem]",
"reason": "aggregation",
"time": "0.9664500000ms"
}
]
}
]
}
]
GROUP BY floor(market_cap / last_sale)
SQL
$ cat << EOF | ./es_query.py http://127.0.0.1:9200
SELECT shares_count, COUNT(*) FROM symbol GROUP BY floor(market_cap / last_sale / 1000000) AS shares_count ORDER BY shares_count LIMIT 3
EOF
{"shares_count": "0.0", "COUNT(*)": 6007}
{"shares_count": "1.0", "COUNT(*)": 328}
{"shares_count": "10.0", "COUNT(*)": 6}
Elasticsearch
{
"aggs": {
"shares_count": {
"terms": {
"size": 3,
"order": {
"_term": "asc"
},
"script": {
"lang": "expression",
"inline": "floor(doc[`market_cap`].value / doc[`last_sale`].value / 1000000)"
}
},
"aggs": {}
}
},
"size": 0
}
如果引用了多個欄位,則無法使用_value,而只能用doc[`market_cap`].value 這樣來引用欄位。
{
"hits": {
"hits": [],
"total": 6714,
"max_score": 0.0
},
"_shards": {
"successful": 1,
"failed": 0,
"total": 1
},
"took": 6,
"aggregations": {
"shares_count": {
"buckets": [
{
"key": "0.0",
"doc_count": 6007
},
{
"key": "1.0",
"doc_count": 328
},
{
"key": "10.0",
"doc_count": 6
}
],
"sum_other_doc_count": 373,
"doc_count_error_upper_bound": 0
}
},
"timed_out": false
}
Profile
[
{
"query": [
{
"query_type": "MatchAllDocsQuery",
"lucene": "*:*",
"time": "0.5422700000ms",
"breakdown": {
"score": 0,
"create_weight": 14630,
"next_doc": 475299,
"match": 0,
"build_scorer": 52341,
"advance": 0
}
}
],
"rewrite_time": 5085,
"collector": [
{
"name": "MultiCollector",
"reason": "search_multi",
"time": "7.627612000ms",
"children": [
{
"name": "TotalHitCountCollector",
"reason": "search_count",
"time": "0.4945110000ms"
},
{
"name": "StringTermsAggregator: [shares_count]",
"reason": "aggregation",
"time": "5.193886000ms"
}
]
}
]
}
]
可以看到這裡使用的是 StringTermsAggregator,這說明了計算結果是用字串來排序的。