Elasticsearch 数据搜索篇

curl 'localhost:9200/_cat/indices?v'
health index pri rep docs.count docs.deleted store.size pri.store.size
yellow bank    5   1       1000            0    424.4kb        424.4kb

搜索API

ES提供了两种搜索的方式:请求参数方式 和 请求体方式数据库

请求参数方式网络

curl 'localhost:9200/bank/_search?q=*&pretty'

其中bank是查询的索引名称,q后面跟着搜索的条件:q=*表示查询全部的内容dom

请求体方式(推荐这种方式)curl

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} }
}'

这种方式会把查询的内容放入body中,会形成必定的开销,可是易于理解。在平时的练习中,推荐这种方式。函数

 

返回的内容搜索引擎

复制代码

{
  "took" : 26,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "1",
      "_score" : 1.0, "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "6",
      "_score" : 1.0, "_source" : {"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
    }, {
      "_index" : "bank",
      "_type" : "account",
      "_id" : "13",

复制代码

返回的内容大体能够以下讲解:url

took:是查询花费的时间,毫秒单位spa

time_out:标识查询是否超时排序

_shards:描述了查询分片的信息,查询了多少个分片、成功的分片数量、失败的分片数量等索引

hits:搜索的结果,total是所有的知足的文档数目,hits是返回的实际数目(默认是10)

_score是文档的分数信息,与排名相关度有关,参考各大搜索引擎的搜索结果,就容易理解。 

因为ES是一次性返回全部的数据,所以理解返回的内容是很必要的。它不像传统的SQL是先返回数据的一个子集,再经过数据库端的游标不断的返回数据(因为对传统的数据库理解的不深,这里有错还望指正)。

查询语言DSL

ES支持一种JSON格式的查询,叫作DSL,domain specific language。这门语言刚开始比较难理解,所以经过几个简单的例子开始:

下面的命令,能够搜索所有的文档:

{
  "query": { "match_all": {} }
}

query定义了查询,match_all声明了查询的类型。还有其余的参数能够控制返回的结果:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "size": 1
}'

上面的命令返回了全部文档数据中的第一条文档。若是size不指定,那么默认返回10条。

 

下面的命令请求了第10-20的文档。

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "from": 10,
  "size": 10
}'

 

下面的命令指定了文档返回的排序方式:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "sort": { "balance": { "order": "desc" } }
}'

 

执行搜索

上面了解了基本的搜索语句,下面就开始深刻一些经常使用的DSL了。

以前的返回数据都是返回文档的全部内容,这种对于网络的开销确定是有影响的,下面的例子就指定了返回特定的字段:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_all": {} },
  "_source": ["account_number", "balance"]
}'

再回到query,以前的查询都是查询全部的文档,并不能称之为搜索引擎。下面就经过match方式查询特定字段的特定内容,好比查询余额为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" } }
}'

若是咱们想要返回同时包含mill和lane的,能够经过match_phrase查询:

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
  "query": { "match_phrase": { "address": "mill lane" } }
}'

ES提供了bool查询,能够把不少小的查询组成一个更为复杂的查询,好比查询同时包含mill和lane的文档:

复制代码

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

复制代码

修改bool参数,能够改成查询包含mill或者lane的文档:

复制代码

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

复制代码

也能够改写为must_not,排除包含mill和lane的文档:

复制代码

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

复制代码

bool查询能够同时使用must, should, must_not组成一个复杂的查询:

复制代码

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

复制代码

过滤查询

以前说过score字段指定了文档的分数,使用查询会计算文档的分数,最后经过分数肯定哪些文档更相关,返回哪些文档。

有的时候咱们可能对分数不感兴趣,就可使用filter进行过滤,它不会去计算分值,所以效率也就更高一些。

filter过滤能够嵌套在bool查询内部使用,好比想要查询在2000-3000范围内的全部文档,能够执行下面的命令:

复制代码

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

复制代码

ES除了上面介绍过的范围查询range、match_all、match、bool、filter还有不少其余的查询方式,这里就先不一一说明了。

聚合

聚合提供了用户进行分组和数理统计的能力,能够把聚合理解成SQL中的GROUP BY和分组函数。在ES中,你能够在一次搜索查询的时间内,即完成搜索操做也完成聚合操做,这样就下降了屡次使用REST API形成的网络开销。

下面就是经过terms聚合的简单样例:

复制代码

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

复制代码

它相似于SQL中的下面的语句:

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

返回的数据:

复制代码

"hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "group_by_state" : {
      "buckets" : [ {
        "key" : "al",
        "doc_count" : 21
      }, {
        "key" : "tx",
        "doc_count" : 17
      }, {
        "key" : "id",
        "doc_count" : 15
      }, {
        "key" : "ma",
        "doc_count" : 15
      }, {
        "key" : "md",
        "doc_count" : 15
      }, {
        "key" : "pa",
        "doc_count" : 15
      }, {
        "key" : "dc",
        "doc_count" : 14
      }, {
        "key" : "me",
        "doc_count" : 14
      }, {
        "key" : "mo",
        "doc_count" : 14
      }, {
        "key" : "nd",
        "doc_count" : 14
      } ]
    }
  }
}

复制代码

因为size设置为0,它并无返回文档的信息,只是返回了聚合的结果。

好比统计不一样帐户状态下的平均余额:

复制代码

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

复制代码

聚合支持嵌套,举个例子,先按范围分组,在统计不一样性别的帐户余额:

复制代码

curl -XPOST 'localhost:9200/bank/_search?pretty' -d '

{
  "size": 0,
  "aggs": {
    "group_by_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 20,
            "to": 30
          },
          {
            "from": 30,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "group_by_gender": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  }
}'

复制代码

聚合能够实现不少复杂的功能,并且ES也提供了不少复杂的聚合,这里做为引导篇,也不过多介绍了。

相关文章
相关标签/搜索