Elasticsearch搜索与分析

前言

本文档主要简单记录一下在ElasticSearch中的一些搜索语句(基于阿里云ElasticSearch环境)。数组

轻量搜索

最简单的搜索应该就是一个简单的get了,以下使用get来获取数据:阿里云

GET /index_name/_search

 

返回结果:spa

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 20,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "index_name",
        "_type" : "_doc",
        "_id" : "11",
        "_score" : 1.0,
        "_source" : {
          "tags" : [
            "gamegroup"
          ],
          "update_time" : 1607156354,
          "@timestamp" : "2021-02-18T03:40:01.235Z",
          "id" : 11,
          "name" : "对马岛之魂",
          "status" : 0,
          "create_time" : 1603073095,
          "@version" : "1",
        }
      },
      ···
    ]
  }
}

 

能够看到咱们从index_name中获取了10条数据(默认返回10条),返回的结果在数组hits中。须要注意的是,返回结果不单单是告知匹配到了哪一些文档,还包含了文档自己的全部数据。rest

同时,针对简单匹配的搜索,咱们也能够直接使用轻量搜索,在请求路径中使用_search端点,并将查询条件赋值给参数q。以下:code

GET /index_name/_search?q=name:马岛

 

返回结果:orm

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 5.1153607,
    "hits" : [
      {
        "_index" : "index_name",
        "_type" : "_doc",
        "_id" : "11",
        "_score" : 5.1153607,
        "_source" : {
          "update_time" : 1607156354,
          "@timestamp" : "2021-02-18T03:40:01.235Z",
          "id" : 11,
          "name" : "对马岛之魂",
          "status": 0,
          "create_time" : 1603073095,
          "@version" : "1",
        }
      }
    ]
  }
}

 

查询表达式搜索

按上面的查询咱们能够实现最简单的搜索方式,可是在实际应用中存在很大的局限性,由于搜索业务的复杂性每每不会如此简单。全部ElasticSearch提供了一个丰富灵活的查询语句叫作查询表达式,它支持更加复杂的查询。 好比:blog

GET /index_name/_search
{
  "query": {
    "match": {
      "name": "活动"
    }
  },
  "sort": [
    {
      "id": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 10
}

 

上面的查询方式主要实现的是,查询name能与活动相匹配的数据,偏移量为0,获取10条数据,同时按照id进行排序(在没有指定排序方式的状况下,默认按照匹配分数_source排序)。排序

复杂查询

下面进行一些相比刚才要更为复杂的查询,查询index_name下的数据,要求name能够匹配关键字“马岛”,同时须要rank_num的值大于5。ip

GET /index_name/_search
{
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "name" : "马岛" 
                }
            },
            "filter": {
                "range" : {
                    "rank_num" : { "gt" : 5 } 
                }
            }
        }
    }
}

 

短语匹配

这里简单介绍一下match与match_phrase,match匹配会将关键词进行拆分品牌,而match_phrase不会将关键词拆分。因此若是须要匹配短语的话,使用match_phrase替代match便可。文档

 1 GET /index_name/_search
 2 {
 3     "query" : {
 4         "bool": {
 5             "must": {
 6                 "match_phrase" : {
 7                     "name" : "马岛" 
 8                 }
 9             },
10             "filter": {
11                 "range" : {
12                     "rank_num" : { "gt" : 5 } 
13                 }
14             }
15         }
16     }
17 }

 

高亮搜索(实践于官方文档有异,待肯定)

许多应用都倾向于在每一个搜索结果中 高亮 部分文本片断,以便让用户知道为什么该文档符合查询条件。在 Elasticsearch 中检索出高亮片断也很容易。在前面的查询中添加一个highlight字段便可。

简单分析

Elasticsearch 有一个功能叫聚合(aggregations),容许咱们基于数据生成一些精细的分析结果。聚合与 SQL 中的 GROUP BY 相似但更强大。 以下(按照parent_id字段进行聚合):

1 GET /index_name/_search
2 {
3   "aggs": {
4     "all_interests": {
5       "terms": { "field": "parent_id" }
6     }
7   }
8 }

 

返回结果:

 1 {
 2    ...
 3    "hits": { ... },
 4    "aggregations": {
 5       "all_interests": {
 6          "buckets": [
 7             {
 8               "key" : 0,
 9               "doc_count" : 66422
10             },
11             {
12               "key" : -1,
13               "doc_count" : 4716
14             },
15             {
16               "key" : 27490,
17               "doc_count" : 1684
18             },
19             ...
20          ]
21       }
22    }
23 }

 

能够看到表中,parent_id字段每一种数据占的数量多少。 同时咱们能够在查询时添加一下搜索语句:

GET /index_name/_search
{
  "query": {
    "match": {
      "platform": "pc"
    }
  },
  "aggs": {
    "all_interests": {
      "terms": { "field": "parent_id" }
    }
  }
}

 

返回结果:

 1 {
 2    ...
 3    "hits": { ... },
 4    "aggregations": {
 5       "all_interests": {
 6          "buckets": [
 7             {
 8               "key" : 0,
 9               "doc_count" : 52428
10             },
11             {
12               "key" : -1,
13               "doc_count" : 3494
14             },
15             {
16               "key" : 27490,
17               "doc_count" : 1684
18             },
19             ...
20          ]
21       }
22    }
23 }

 

分级汇总

查询方式:

 1 GET /megacorp/employee/_search
 2 {
 3     "aggs" : {
 4         "all_interests" : {
 5             "terms" : { "field" : "interests" },
 6             "aggs" : {
 7                 "avg_age" : {
 8                     "avg" : { "field" : "age" }
 9                 }
10             }
11         }
12     }
13 }

 

返回结果:

...
  "all_interests": {
     "buckets": [
        {
           "key": "music",
           "doc_count": 2,
           "avg_age": {
              "value": 28.5
           }
        },
        {
           "key": "forestry",
           "doc_count": 1,
           "avg_age": {
              "value": 35
           }
        },
        {
           "key": "sports",
           "doc_count": 1,
           "avg_age": {
              "value": 25
           }
        }
     ]
  }

 

返回结果也是很好理解的,如最后一条数据表示sports的数量为1,平均年龄为25。