搜索你的数据

前面我们讲了如何通过RESTful API创建索引,那么如何搜索已经存在的索引数据呢?

搜索API

Elasticsearch提供了两种基本的方式进行搜索:一种是通过REST请求URI传递搜索参数,另一种是通过REST请求体传递参数。搜索的REST API是”_search”,下面的命令是要搜索bank中的所有数据:

curl ‘localhost:9200/userindex/_search?q=*&pretty’

响应的结果(部分)如下:

{
    "took": 663,
    "timed_out": false,
    "_shards": {
        "total": 16,
        "successful": 16,
        "failed": 0
    },
    "hits": {
        "total": 307843698,
        "max_score": 1,
        "hits": [
            {
                "_index": "userindex",
                "_type": "951",
                "_id": "95131620",
                "_score": 1,
                "_source": {
                    "uid": 95131620,
                    "cell": "1725895131620",
                    "appId": "951",
                    "phoneType": "ANDROID",
                    "province": "北京",
                    "tags": "1 2 3 4 5”,
                    "city": "11000000",
                    "sex": 70,
                    "price": 1000,
                    "usertype": "10001",
                    "mobiler": "1",
                    "userTag": ""
                }
            }
        ]
    }
}

其中,部分字段的含义如下:

took:花费的时间

time_out:显示是否超时

_shards:搜索了多少分片,成功/失败搜索的分片数量

hits:搜索命中的结果

hits.total:命中的数量

_score和max_score:匹配得分

第二种搜索方式,使用请求体:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
    “query”: {“match_all”: {} }
}’

查询简介

对上面的查询语句,”query”部分表示要进行查询操作,而”match_all”表示得到索引中的全部文档。除了”query”参数,还可以增加其他参数,比如还是要搜索全部文档,不过只返回第一个文档:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
      “query”: { “match_all”: {} },
      “size”: 1
}’

如果”size”未特别说明,默认返回10条结果。下面的例子返回文档11到20:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
       “query”: { “match_all”: {} },
       “from”: 10,
       “size”: 1
}’

当对搜索结果分页时,这个功能非常有用。下面的例子返回10条结果(默认size)并根据balance降序排序:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ’
{
       “query”: {“match_all”: {} },
       “sort”: {“balance”: {“orde”: “desc”}}
}’

查询操作

之前的查询都将源数据全部返回,现在介绍只让我们想要的字段返回,比如下面的例子只返回两个字段”account_number”和”balance”:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d  ‘
{      
       “query”: {“match_all”: {} } ,
       “_source”: [“account_number”, “balance”]
}’

然后再看”query”字段的匹配,比如下面的例子返回编号是20的账户:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
      “query”: {“match”:{ “account_number”:20 } }
}’

然后返回地址中包含”mill”的账户:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
      “query”: {“match”: {“address”: “mill”}}
}’

下面的例子返回的结果是地址中包含”mill”或”lane”的账户:

$curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d ‘
{
      “query”: {“match”: {“address”: ”mill lane”}}
}’

区别上面的例子,使用”match_phrase”关键词,下面的例子返回包含词组”mill lane”的账户:

curl –XPOST ‘localhost:9200/bank/_search?pretty’ –d
{
       “query” : {“match_phrase”: {“address”:”mill lane”}}
}’

下面在介绍一些布尔查询的例子,首先介绍与查询:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
     "query": {
           "bool": {
                "must": [
                     { "match": { "address": "mill" } },
                     { "match": { "address": "lane" } }
                 ]
           }
     }
}'

返回地址中既包含”mill”又包含”lane”的账户。然后或查询,地址中包含”mill”或”lane”:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
      "query": {
            "bool": {
                 "must": [
                      { "match": { "address": "mill" } },
                      { "match": { "address": "lane" } }
                 ]
            }
     }
}'

既不包含”mill”又不包含”lane”:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
      "query": {
            "bool": {
                 "must_not": [
                           { "match": { "address": "mill" } },
                           { "match": { "address": "lane" } }
                  ]
             }
       }
}'

在布尔查询中,可以随意组合布尔子句,例如下面的子句查询年龄40岁,但不在ID州的账户:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
      "query": {
            "bool": {
                 "must": [
                       { "match": { "age": "40" } }
                 ],
                 "must_not": [
                       { "match": { "state": "ID" } }
                 ]
             }
       }
}'

使用过滤器

前面介绍过查询结果中会回馈一个字段”_score”,这是查询和文档相关度的一个度量,值越大表示相关度越大,而值越小表示相关度越小。但有时,Elasticsearch提供了另一查询功能——过滤器。过滤器和查询的概念相似,但却比查询要快,基于下面两个原因:

(1) 过滤器不需要评分

(2) 过滤器通过缓存使得重复检索速度非常快

过滤器可以和查询一起使用,例如下面的例子查询余额在20000到30000之间(包含)的账号:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
      "query": {
            "filtered": {
                   "query": { "match_all": {} },
                         "filter": {
                                "range": {
                                      "balance": {
                                            "gte": 20000,
                                            "lte": 30000
                                       }
                                 }
                        }
                   }
          }
}'

这个命令包含了一个”match_all”查询和一个范围过滤器

使用聚合

聚合提供了分组和统计的能力,关于聚合的理解,可以类比SQL中的GROUP BY或SQL聚合函数。下面的例子将所有的账户按照州聚合,并且按照默认值返回排名前10的州,并按照默认的降序排列:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
       "size": 0,
            "aggs": {
                 "group_by_state": {
                         "terms": {
                               "field": "state"
                         }
                 }
            }
}'

上面的命令类似于SQL中的:

SELECT COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC