Elasticsearch5入门(6)检索数据

入门(6)检索你的数据

测试数据

我们已经掌握了一些基础知识,现在我们来操作一些更真实的数据-客户银行账户数据。点击这里获取json,并利用前面的知识插入到es中!

POST bank/account/_bulk?pretty
{"index":{"_id":"1"}}
{"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":{"_id":"6"}}
{"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"}
...

Search API

搜索有两种基本的方法:

  • 一种是通过REST请求URI发送搜索参数,。
  • 一种是通过REST请求体发送参数。请求体方法更具表现力,并且还可以以更可读的JSON格式定义搜索。 我们举一个请求URI方法的示例,但是在本教程的其余部分中,我们使用请求体方法。

**用于搜索的REST API以_search开头。此示例返回银行索引中的10条文档: **

GET bank/_search?q=*&sort=account_number:asc&pretty

我们来看一下搜索语句。我们在bank index中搜索(_search ):

  • q = *参数表示Elasticsearch匹配索引中的所有文档。
  • sort = account_number:asc参数表示使用每个文档的account_number字段按升序对结果进行排序。 漂亮的参数再次告诉Elasticsearch返回漂亮打印的JSON结果。 之所以返回10条不是所有是因为有个size参数,在不指定的情况下默认为10。 如果指定的话,语句这样写
GET bank/_search?q=*&sort=account_number:asc&size=1000&pretty

响应: ![](http:// orma7vo6f.bkt.clouddn.com/wiki/ElasticSearch5.4官方文档-中文翻译/_image/2017-06-16-17-22-45.jpg)

我们来看一下上面响应中的参数:

  • took -Elasticsearch执行搜索的时间(毫秒)
  • timed_out - 搜索是否超时
  • _shards -搜索了多少个分片,以及成功/失败的搜索分片数
  • hits - 搜索结果
  • hits.total - 符合搜索条件的文件总数
  • hits.hits - 搜索结果的实际数组(默认为前10个文档)
  • hits.sort - 结果的排序键(如果按分数排序,则丢失)
  • hits._scoremax_score - 现在忽略这些字段

下面是使用请求体方法做与上面效果相同的搜索:

GET bank/_search
{
  "query": { "match_all": {} },
  "size": 1000, 
  "sort": [
    { "account_number": "asc" }
  ]
}

这里的不同之处在于,我们不会在URI中传递q = *,而是向_search API发布一个JSON样式的查询请求体。我们将在下一节中讨论这个JSON查询。

重要的是要明白,一旦你获得了搜索结果,Elasticsearch就完成了这个请求,并且不会保留任何类型的服务器端资源或打开游标到你的结果中。这与许多其他平台(如SQL)形成鲜明对比,您可能最初会先获得查询结果的部分子集,然后如果要获取(或浏览)其余部分,则必须不断返回到服务器的结果使用某种有状态的服务器端游标。 上面这句话尽量理解吧!

介绍查询语言(Introducing the Query Language)

Elasticsearch提供了一种可用于执行查询的JSON风格的的语言。这被称为查询DSL。查询语言是相当全面的,乍看起来可能很吓人,我们先来看几个例子!

回到我们的最后一个例子,我们执行了这个查询:

GET bank/_search
{
  "query": { "match_all": {} },
  "size": 1000, 
  "sort": [
    { "account_number": "asc" }
  ]
}

解析上面的内容: query部分告诉我们,我们的查询定义是什么。 match_all部分只是我们要运行的查询类型。 match_all查询只是搜索指定索引中的所有文档。 除查询参数外,我们还可以传递其他参数来影响搜索结果。在上面的例子中我们通过排序(sort),大小(size)!

再次提醒,如果未指定大小,则默认为10。

此示例执行一个match_all并返回文档11到20:

GET bank/_search
{
  "query":{
    "match_all": {}
  },
  "from": 0,
  "size": 10
}

from参数(基于0)指定要从哪个文档索引开始, size参数指定从from参数开始返回多少个文档。执行搜索结果分页时,此功能非常有用。请注意,如果未指定from,则默认为0。

此示例执行match_all,并按结果按降序排列帐户余额,并返回前10名(默认大小)文档。

GET bank/_search
{
  "query":{
    "match_all": {}
  },
  "sort": {
    "balance":{"order":"desc"}
  },
  "from": 0,
  "size": 10
}

执行搜索(Executing Searches)

现在我们已经看到了一些基本的搜索参数,我们来进一步探讨Query DSL。我们先来看看返回的文档字段。默认情况下,完整的JSON文档作为搜索结果的一部分返回。这被称为(搜索结果中的_source字段)。如果我们不希望返回整个源文档,我们可以指定返回的字段。

此示例显示如何从指定搜索字段:

GET bank/_search
{
  "query":{"match_all": {}},
  "_source":["account_number","balance"]
}

如果您有SQL背景,上述内容在概念上与SQL SELECT FROM字段列表有些相似。

现在看查询部分。前面我们已经看到了如何使用match_all查询来匹配所有文档。 现在我们来介绍一个称为匹配查询的新查询,它是基本的字段搜索查询(即针对特定字段或一组字段进行搜索)。

此示例返回的帐号为20:

GET bank/_search
{
  "query": { "match": { "account_number": 20 } }
}

下面示例返回在地址中包含“mill”的所有帐户:

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  }
}

此示例返回在地址中包含术语“mill”或“lane”的所有帐户:

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill lane"
    }
  }
}

此示例返回所有包含地址中包含“mill lane”短语的帐户:

GET /bank/_search
{
  "query": { "match_phrase": { "address": "mill lane" } }
}

bool查询

现在介绍一下bool(ean)查询。 bool查询允许我们使用布尔逻辑将更小的查询组合成较大的查询。(其实就是条件表达式)

** 查询地址中包含“mill”“lane”的所有帐户: **

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "address": "lane"
          }
        }
      ]
    }
  }
}

查询地址中包含“mill”“lane”的所有帐户:

GET /bank/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

查询地址中既不包含“mill”也不包含“lane”的所有帐户:

GET /bank/_search
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "address": "mill" } },
        { "match": { "address": "lane" } }
      ]
    }
  }
}

我们可以在一个bool查询中,同时结合使用must,should和must_not子句。此外,我们可以在任何这些bool子句中组合bool查询,以实现任何复杂的多级boolean逻辑。

查询所有age为40但是state不为id的帐户:

GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "age": "40" } }
      ],
      "must_not": [
        { "match": { "state": "ID" } }
      ]
    }
  }
}

执行过滤(Filter)

在上一节中,我们跳过了一些名为文档分数的细节(搜索结果中的_score字段)。分数是一个数字值,它是文档与我们指定的搜索查询匹配相对度量。分数越高,文档越相关,分数越低,文档的相关性越低。

但查询并不总是需要生成分数,特别是当它们仅用于“过滤”文档集时。Elasticsearch检测这些情况和自动优化查询执行为了不计算无用的分数。

bool查询也支持filter 条件,它不改变计算分数。例如,我们来介绍一下范围查询,它允许我们通过一系列值过滤文档。通常用于数字或日期过滤。

查询余额(balance)在20000和30000之间的所有账户。换句话说,我们希望找到大于等于20000,小于等于30000的账户。

GET /bank/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "balance": {
            "gte": 20000,
            "lte": 30000
          }
        }
      }
    }
  }
}

在上面的例子中,布尔(bool)查询包含match_all查询(查询的一部分)和范围(range)查询(过滤[filter]部分)。在上面的例子中,使用范围查询是完全合理的,因为没有一个文档比另一个文档相关性更高。

除了match_allmatchboolrange查询之外,还有很多其他可用的查询类型,我们不会在这里查看。既然我们已经对它们有了基本的了解,将这些知识应用于学习和实验其他查询类型并不难。

执行聚合(Executing Aggregations)

聚合(Aggregations )提供:对数据中分组提取统计信息的功能。 理解聚合的最简单的方法是将它大致看作SQL GROUP BY和SQL聚合函数。在Elasticsearch中,你可以在一次查询中执行多个聚合,他们都会分别在返回结果中展示,这样的效率是比较高的。

此示例按状态(state)分组,然后返回按count降序排序的前10个(默认):

GET bank/_search
{
  "size": 0
  , "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      }
    }
  }
}

在SQL中,上述聚合在概念上类似于:

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

响应(部分显示):

{
    "took": 281,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 999,
        "max_score": 0,
        "hits": []
    },
    "aggregations": {
        "group_by_state": {
            "doc_count_error_upper_bound": 20,
            "sum_other_doc_count": 770,
            "buckets": [
                {
                    "key": "ID",
                    "doc_count": 27
                },
                {
                    "key": "TX",
                    "doc_count": 27
                },
                {
                    "key": "AL",
                    "doc_count": 25
                },
                {
                    "key": "MD",
                    "doc_count": 25
                }
            ]
        }
    }
}

我们可以看到,ID(爱达荷州州)有27个帐户,其次是TX(德克萨斯州)的27个帐户,其次是AL(阿拉巴马州)25个帐户,等等。

请注意,我们将size = 0,设置为不显示搜索结果(只显示聚合结果),因为我们只想在响应中看到聚合结果。

在前面的聚合基础上,本例通过状态计算平均帐户余额(仅用于按降序排序的前10个状态):

GET bank/_search
{
  "size": 0
  , "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword"
      }
      , "aggs": {
        "avg_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  }
}

注意我们如何嵌套group_by_state聚合中的average_balance聚合。这是所有聚合的常见模式。您可以任意嵌套聚合内的聚合。

基于上一个汇总,我们现在按照降序对平均余额进行排序:

GET bank/_search
{
  "size": 0
  , "aggs": {
    "group_by_state": {
      "terms": {
        "field": "state.keyword",
        "order": {
          "avg_balance": "desc"
        }
      }
      , "aggs": {
        "avg_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
      
    }
  }
}

这个例子演示了先按年龄段(20-29岁,30-39岁和40-49岁)分组,再按按性别分组,最终得到每个年龄段的平均账户余额:

GET /bank/_search
{
  "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.keyword"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      }
    }
  }
}

还有许多其他聚合功能,我们将不再详细介绍。如果您想进一步探索,点击:聚合参考指南

转载于:https://my.oschina.net/shibuyisha/blog/968297

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值