elasticsearch入门使用

该文章基于:http://blog.csdn.net/gl775307284/article/details/44731009 整理而来javascript

基础概念

一、接近实时(NRT)
Elasticsearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档可以被搜索到有一个轻微的延迟(一般是1秒)html

二、集群(cluster)
一个集群就是由一个或多个节点组织在一块儿,它们共同持有你整个的数据,并一块儿提供索引和搜索功能。
一个集群由一个惟一的名字标识,这个名字默认就是 “elasticsearch”。
这个名字是重要的,由于一个节点只能经过指定某个集群的名字,来加入这个集群。
在产品环境中显式地设定这个名字是一个好习惯,可是使用默认值来进行测试/开发也是不错的。java

三、节点(node)
一个节点是你集群中的一个服务器,做为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。
和集群相似,一个节点也是由一个名字来标识的,默认状况 下,这个名字是一个随机的漫威漫画角色的名字,
这个名字会在启动的时候赋予节点。这个名字对于管理工做来讲挺重要的,由于在这个管理过程当中,
你会去肯定网 络中的哪些服务器对应于Elasticsearch集群中的哪些节点。
一个节点能够经过配置集群名称的方式来加入一个指定的集群。
默认状况下,每一个节点都会被安排加入到一个叫作“elasticsearch”的集群中,这意 味着,
若是你在你的网络中启动了若干个节点,并假定它们可以相互发现彼此,它们将会自动地造成并加入到一个叫作“elasticsearch”的集群中。
在一个集群里,只要你想,能够拥有任意多个节点。并且,若是当前你的网络中没有运行任何Elasticsearch节点,
这时启动一个节点,会默认建立并加入一个叫作“elasticsearch”的集群。node

四、索引(index)
一个索引就是一个拥有几分类似特征的文档的集合。好比说,你能够有一个客户数据的索引,另外一个产品目录的索引,还有一个订单数据的索引。
一个索引由一个名 字来标识(必须所有是小写字母的),而且当咱们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。
在一个集群中,若是你想,能够定义任意多的索引。git

五、类型(type)
在一个索引中,你能够定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义彻底由你来定。
一般,会为具备一组共同字段的文档定义一个 类型。好比说,咱们假设你运营一个博客平台而且将你全部的数据存储到一个索引中。
在这个索引中,你能够为用户数据定义一个类型,为博客数据定义另外一个类 型,固然,也能够为评论数据定义另外一个类型。github

六、文档(document)
一个文档是一个可被索引的基础信息单元。好比,你能够拥有某一个客户的文档,某一个产品的一个文档,
固然,也能够拥有某个订单的一个文档。文档以 JSON(Javascript Object Notation)格式来表示,而JSON是一个处处存在的互联网数据交互格式。
在一个index/type里面,只要你想,你能够存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。json

七、分片和复制(shards & replicas)
  • 一个索引能够存储超出单个结点硬件限制的大量数据。好比,一个具备10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。    为了解决这个问题,Elasticsearch提供了将索引划分红多份的能力,这些份就叫作分片。 当你建立一个索引的时候,你能够指定你想要的分片的数量。每一个分片自己也是一个功能完善而且独立的“索引”,这个“索引”能够被放置到集群中的任何节点上。
  • 分片之因此重要,主要有两方面的缘由:

- 容许你水平分割/扩展你的内容容量windows

- 容许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操做,进而提升性能/吞吐量api

  •  至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是彻底由Elasticsearch管理的,对于做为用户的你来讲,这些都是透明的
  • 在一个网络/云的环境里,失败随时均可能发生,在某个分片/节点不知怎么的就处于离线状态,或者因为任何缘由消失了,这种状况下,有一个故障转移机制是非 常有用而且是强烈推荐的。为此目的,Elasticsearch容许你建立分片的一份或多份拷贝,这些拷贝叫作复制分片,或者直接叫复制。
  • 复制之因此重要,有两个主要缘由:

- 在分片/节点失败的状况下,提供了高可用性。由于这个缘由,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是很是重要的。浏览器

- 扩展你的搜索量/吞吐量,由于搜索能够在全部的复制上并行运行

  • 总之,每一个索引能够被分红多个分片。一个索引也能够被复制0次(意思是没有复制)或屡次。一旦复制了,每一个索引就有了主分片(做为复制源的原来的分片)和 复制分片(主分片的拷贝)之别。分片和复制的数量能够在索引建立的时候指定。在索引建立以后,你能够在任什么时候候动态地改变复制的数量,可是你过后不能改变 分片的数量。
  • 默认状况下,Elasticsearch中的每一个索引被分片5个主分片和1个复制,这意味着,若是你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个彻底拷贝),这样的话每一个索引总共就有10个分片。

安装

一、环境:JDK使用java 1.8(安装省略),elasticsearch 2.3.4,window系统

二、下载解压后,在bin目录中运行elasticsearch.bat

此处的节点名称:Vermin

咱们能够覆盖集群或者节点的名字。咱们能够在启动Elasticsearch的时候经过命令行来指定,以下:
elasticsearch.bat --cluster.name my_cluster_name --node.name my_node_name

 

三、提供了有关HTTP地址(192.168.8.112)和端口(9200)的信息,经过这个地址和端口咱们就能够 访问咱们的节点了。
默认状况下,Elasticsearch使用9200来提供对其REST API的访问。若是有必要,这个端口是能够配置的

访问地址:http://127.0.0.1:9200/

 

利用rest api通讯

  • 检查你的集群、节点和索引的健康状态、和各类统计信息
  • 管理你的集群、节点、索引数据和元数据
  • 对你的索引进行CRUD(建立、读取、更新和删除)和搜索操做
  • 执行高级的查询操做,像是分页、排序、过滤、脚本编写(scripting)、小平面刻画(faceting)、聚合(aggregations)和许多其它操做

为了方便在对elasticsearch通讯,安装插件sense,因为google被墙,没法访问Google 商店,所以建议使用360浏览器安装sense插件,安装方法(略)

 

一、集群健康

访问的URL: [html]  view plain  copy
  1. http://127.0.0.1:9200/_cat/health?v  
响应: [html]  view plain  copy
  1. epoch      timestamp cluster       status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent   
  2. 1512722087 16:34:47  elasticsearch green           1         1      0   0    0    0        0             0                  -                100.0%   
  • 集群的名字是“elasticsearch”,正常运行,而且状态是绿色。

(1)当咱们询问集群状态的时候,咱们要么获得绿色、黄色或红色

绿色表明一切正常(集群功能齐全)

黄色意味着全部的数据都是可用的,可是某些复制没有被分配 (集群功能齐全)

红色则表明由于某些缘由,某些数据不可用。注意,即便是集群状态是红色的,集群仍然是部分可用的(它仍然会利用可用的分片来响应搜索请 求),可是可能你须要尽快修复它,由于你有丢失的数据。

(2)从上面的响应中,咱们能够看到,一共有一个节点,因为里面没有数据,咱们有0个分片。注意,因为咱们使用默认的集群名字 (elasticsearch),而且因为Elasticsearch默认使用网络多播(multicast)发现其它节点,若是你在你的网络中启动了多 个节点,你就已经把她们加入到一个集群中了。在这种情形下,你可能在上面的响应中看到多个节点。

二、列出节点列表

访问的URL(GET请求):

 

[html] view plain copy

  1. http://127.0.0.1:9200/_cat/nodes?v  
响应:

 

[html] view plain copy

  1. host      ip        heap.percent ram.percent  load node.role master name        
  2. 127.0.0.1 127.0.0.1            7          63 -1.00 d         *      Mary Zero   
从中能够看到节点是Mary Zero

 

三、列出全部的索引

访问的URL(GET请求):

 

[html] view plain copy

  1. http://127.0.0.1:9200/_cat/indices?v  
响应:

 

[html] view plain copy

  1. health status index pri rep docs.count docs.deleted store.size pri.store.size   
从中能够看到尚未索引

 

四、建立一个索引

建立一个叫“customer”的索引

访问地址,使用sense插件请求(PUT请求):

 

[html] view plain copy

  1. 127.0.0.1:9200/customer?pretty  
响应:

 

[html] view plain copy

  1. {  
  2.    "acknowledged": true  
  3. }  
因为加入了pretty在尾部,会打印出美观的json形式

列出全部索引(参考 3)

 

[html] view plain copy

  1. health status index    pri rep docs.count docs.deleted store.size pri.store.size   
  2. yellow open   customer   5   1          0            0       650b           650b   

这个customer索引有一个黄色健康标签。回顾咱们以前的讨论,黄色意味着某些复制没有(或者还未)被分配。这个索引之因此这样,是 由于Elasticsearch默认为这个索引建立一份复制。因为如今咱们只有一个节点在运行,那一份复制就分配不了了(为了高可用),直到当另一个节 点加入到这个集群后,才能分配。一旦那份复制在第二个节点上被复制,这个节点的健康状态就会变成绿色。

索引并查询文档

 

利用以前建立的customer索引进行相关文档操做,使用sense插件,server:127.0.0.1:9200

首先要知道的是,为了索引一个文档,咱们必须告诉Elasticsearch这个文档要到这个索引的哪一个类型(type)下。

 

一、将一个简单的客户文档索引到customer索引、“external”类型中,这个文档的ID是1

 

[html]  view plain  copy
  1. PUT /customer/external/1?pretty  
  2. {  
  3.     "name":"Johe Done"  
  4. }  
响应:

 

 

[html]  view plain  copy
  1. {  
  2.    "_index": "customer",  
  3.    "_type": "external",  
  4.    "_id": "1",  
  5.    "_version": 1,  
  6.    "_shards": {  
  7.       "total": 2,  
  8.       "successful": 1,  
  9.       "failed": 0  
  10.    },  
  11.    "created": true  
  12. }  
从上面的响应中,咱们能够看到,一个新的客户文档在customer索引和external类型中被成功建立。文档也有一个内部id 1, 这个id是咱们在索引的时候指定的。
有一个关键点须要注意,Elasticsearch在你想将文档索引到某个索引的时候,并不强制要求这个索引被显式地建立。
在前面这个例子中,若是customer索引不存在,Elasticsearch将会自动地建立这个索引。

 

二、取出建立的文档

 

[html]  view plain  copy
  1. GET /customer/external/1?pretty  

响应:

 

 

[html]  view plain  copy
  1. {  
  2.    "_index": "customer",  
  3.    "_type": "external",  
  4.    "_id": "1",  
  5.    "_version": 2,  
  6.    "found": true,  
  7.    "_source": {  
  8.       "name": "Johe Done"  
  9.    }  
  10. }  

三、删除建立的索引

 

 

[html]  view plain  copy
  1. DELETE /customer?pretty  
响应:

 

 

[html]  view plain  copy
  1. {  
  2.    "acknowledged": true  
  3. }  
在查看索引(参考 :列出全部索引)

 

响应:

 

[html]  view plain  copy
  1. health status index pri rep docs.count docs.deleted store.size pri.store.size   
这代表咱们成功地删除了这个索引,如今咱们回到了集群中空无全部的状态

 

 

四、修改数据

Elasticsearch提供了近乎实时的数据操做和搜索功能。默认状况下,从你索引/更新/删除你的数据动做开始到它出如今你的搜索结果中,

大概会有1秒钟的延迟。这和其它相似SQL的平台不一样,数据在一个事务完成以后就会当即可用。

先添加ID:1,name:Johe Done

 

[html]  view plain  copy
  1. PUT /customer/external/1?pretty  
  2. {  
  3.     "name":"Johe Done"  
  4. }  

 

在添加ID:2,name:Loren

 

[html]  view plain  copy
  1. PUT /customer/external/2?pretty  
  2. {  
  3.     "name":"Loren"  
  4. }  
在索引的时候,ID部分是可选的。若是不指定,Elasticsearch将产生一个随机的ID来索引这个文档。Elasticsearch生成的ID会做为索引API调用的一部分被返回。

 

 

[html]  view plain  copy
  1. POST /customer/external?pretty  
  2. {  
  3.     "name":"Karrt"  
  4. }  
在上面的情形中,因为咱们没有指定一个ID,咱们使用的是POST而不是PUT。

 


五、更新文档

除了能够索引、替换文档以外,咱们也能够更新一个文档。但要注意,Elasticsearch底层并不支持原地更新。在咱们想要作一次更新的时候,Elasticsearch先删除旧文档,而后在索引一个更新过的新文档。

将name的值修改成Lucene

 

[html]  view plain  copy
  1. POST /customer/external/1/_update?pretty  
  2. {  
  3.     "doc":{"name":"Lucene"}  
  4. }  

将name的值修改,并同时添加age字段

 

 

[html]  view plain  copy
  1. POST /customer/external/1/_update?pretty  
  2. {  
  3.     "doc":{"name":"Lucene", "age":50}  
  4. }  
使用脚本将age加10

 

 

[html]  view plain  copy
  1. POST /customer/external/1/_update?pretty  
  2. {  
  3.     "script":"ctx._source.age += 10"  
  4. }  

 

ctx._source指向当前要被更新的文档。

须要开启容许脚本运行

 

在elasticsearch.yml配置文件中添加

 

[html] view plain copy

  1. script.inline: on    
  2. script.indexed: on   
  3. script.engine.groovy.inline.aggs: on   

 

 

六、删除文档

删除ID:2的文档

 

[html] view plain copy

  1. DELETE /customer/external/2?pretty  
经过查询删除多个文档,例如:删除name包含Kerry的文档

 

[html] view plain copy

  1. DELETE /customer/external/_query?pretty  
  2. {  
  3.     "query":{"match": {  
  4.        "name": "Kerry"  
  5.     }}  
  6. }  
注意:在2.x以上版本默认的的Delete by Query API被移除,须要本身按照插件,缘由: https://www.elastic.co/blog/core-delete-by-query-is-a-plugin
在bin目录运行:

 

[html] view plain copy

  1. plugin.bat install delete-by-query  
 集群环境下必须在每一个结点上安装,安装以后要重启结点才能使这个插件生效

 

七、批处理

除了可以对单个的文档进行索引、更新和删除以外,Elasticsearch也提供了以上操做的批量处理功能,这是经过使用_bulk API实现的。

这个功能之因此重要,在于它提供了很是高效的机制来尽量快的完成多个操做,与此同时使用尽量少的网络往返。

批量修改ID:1,ID:2的数据

 

[html]  view plain  copy
  1. POST /customer/external/_bulk?pretty  
  2. {"index":{"_id":"2"}}  
  3. {"name":"kkkkk"}  
  4. {"index":{"_id":"1"}}  
  5. {"name":"enenen"}  

 

 

先修改(ID:1),在删除ID:3

 

[html]  view plain  copy
  1. POST /customer/external/_bulk?pretty  
  2. {"update":{"_id":"1"}}  
  3. {"doc":{"name":"zhangsan"}}  
  4. {"delete":{"_id":"3"}}  
注意上面的delete动做,因为删除动做只须要被删除文档的ID,因此并无对应的源文档

 

bulk API按顺序执行这些动做。若是其中一个动做由于某些缘由失败了,将会继续处理它后面的动做。当bulk API返回时,它将提供每一个动做的状态(按照一样的顺序),因此你可以看到某个动做成功与否。

 

例子学习

一、样本数据集

以客户的银行帐户信息的JSON文档的样本。文档具备如下的模式(schema)

 

[javascript]  view plain  copy
  1. {  
  2.     "account_number": 0,  
  3.     "balance": 16623,  
  4.     "firstname": "Bradshaw",  
  5.     "lastname": "Mckenzie",  
  6.     "age": 29,  
  7.     "gender": "F",  
  8.     "address": "244 Columbus Place",  
  9.     "employer": "Euron",  
  10.     "email": "bradshawmckenzie@euron.com",  
  11.     "city": "Hobucken",  
  12.     "state": "CO"  
  13. }  

二、载入样本数据

样本数据获取:https://github.com/bly2k/files/blob/master/accounts.zip?raw=true

本人不知道如何使用sense读取本地json文件,所以使用GUI bash工具在windows使用curl命令

 

[javascript]  view plain  copy
  1. curl -XPOST '127.0.0.1:9200/bank/account/_bulk?pretty' --data-binary @accounts.json  
查看索引

 

 

[javascript]  view plain  copy
  1. GET /_cat/indices?v  
[html]  view plain  copy
  1. health status index    pri rep docs.count docs.deleted store.size pri.store.size   
  2. yellow open   bank       5   1       1000            0    442.1kb        442.1kb   
  3. yellow open   customer   5   1          3            0      9.4kb          9.4kb   
 

三、搜索API

经过‘_search’来查询调用,而且q=*参数指示Elasticsearch去匹配这个索引中全部的文档。pretty参数,和之前同样,仅仅是告诉Elasticsearch返回美观的JSON结果

 

[html]  view plain  copy
  1. GET /bank/_search?q=*&pretty  
部分响应:

 

[html]  view plain  copy
  1. {  
  2.    "took": 58,  
  3.    "timed_out": false,  
  4.    "_shards": {  
  5.       "total": 5,  
  6.       "successful": 5,  
  7.       "failed": 0  
  8.    },  
  9.    "hits": {  
  10.       "total": 1000,  
  11.       "max_score": 1,  
  12.       "hits": [  
  13.          {  
  14.             "_index": "bank",  
  15.             "_type": "account",  
  16.             "_id": "25",  
  17.             "_score": 1,  
  18.             "_source": {  
  19.                "account_number": 25,  
  20.                "balance": 40540,  
  21.                "firstname": "Virginia",  
  22.                "lastname": "Ayala",  
  23.                "age": 39,  
  24.                "gender": "F",  
  25.                "address": "171 Putnam Avenue",  
  26.                "employer": "Filodyne",  
  27.                "email": "virginiaayala@filodyne.com",  
  28.                "city": "Nicholson",  
  29.                "state": "PA"  
  30.             }  
  31.          },  
  32.          {  
  33.             "_index": "bank",  
  34.             "_type": "account",  
  35.             "_id": "44",  
  36.             "_score": 1,  
  37.             "_source": {  
  38.                "account_number": 44,  
  39.                "balance": 34487,  
  40.                "firstname": "Aurelia",  
  41.                "lastname": "Harding",  
  42.                "age": 37,  
  43.                "gender": "M",  
  44.                "address": "502 Baycliff Terrace",  
  45.                "employer": "Orbalix",  
  46.                "email": "aureliaharding@orbalix.com",  
  47.                "city": "Yardville",  
  48.                "state": "DE"  
  49.             }  
  50.          },  
  51.          {  
  52.             "_index": "bank",  
  53.             "_type": "account",  
  54.             "_id": "99",  
  55.             "_score": 1,  
  56.             "_source": {  
  57.                "account_number": 99,  
  58.                "balance": 47159,  
  59.                "firstname": "Ratliff",  
  60.                "lastname": "Heath",  
  61.                "age": 39,  
  62.                "gender": "F",  
  63.                "address": "806 Rockwell Place",  
  64.                "employer": "Zappix",  
  65.                "email": "ratliffheath@zappix.com",  
  66.                "city": "Shaft",  
  67.                "state": "ND"  
  68.             }  
  69.          },  
响应说明:

took:elasticsearch执行这个搜索的耗时,以毫秒为单位

timed_out:指明这个搜索是否超时

_shards:指出多少个分片被搜索,同时也指出成功/失败的被搜索的shareds数量

hits:搜索的结果

hits.total:可以匹配搜索出文档的总数

hits.hits:真正搜索的数据,默认显示10条

max_score和_score:先忽略

 

另外一种等价的方式:

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match_all": {}}  
  4. }  

这里的不一样之处在于,并非向URI中传递q=*,取而代之的是,咱们在_search API的请求体中POST了一个JSON格式请求体

有一点须要重点理解一下,一旦你取回了你的搜索结果,Elasticsearch就完成了使命,它不会维护任何服务器端的资源或者在你的结果中打开游标。 这是和其它相似SQL的平台的一个鲜明的对比, 在那些平台上,你能够在前面先获取你查询结果的一部分,而后若是你想获取结果的剩余部分,你必须继续返回服务端去取,这个过程使用一种有状态的服务器端游 标技术。

 

四、介绍查询语言

Elasticsearch提供一种JSON风格的特定领域语言,利用它你能够执行查询。这被称为查询DSL。

 

[html]  view plain  copy
  1. {  
  2.     "query": {"match_all": {}}  
  3. }  
分解上面的这个查询,其中的query部分告诉我查询的定义,match_all部分就是咱们想要运行的查询的类型。match_all查询,就是简单地查询一个指定索引下的全部的文档。

除了这个query参数以外,咱们也能够经过传递其它的参数来影响搜索结果

例如只返回一个文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match_all": {}},  
  4.     "size": 1  
  5. }  
size若是没有指定,默认值是10

返回第11到20的文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match_all": {}},  
  4.     "from": 11,   
  5.     "size": 10  
  6. }  
其中的from参数(0-based)从哪一个文档开始,size参数指明从from参数开始,要返回多少个文档。这个特性对于搜索结果分页来讲很是有帮助。注意,若是不指定from的值,它默认就是0

下面的例子:

搜索全部的帐户并余额降序排序,返回前10个文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match_all": {}},  
  4.     "sort": [  
  5.        {  
  6.           "balance": {  
  7.              "order": "desc"  
  8.           }  
  9.        }  
  10.     ]  
  11. }  

五、执行搜索

如今咱们已经知道了几个基本的参数,让咱们进一步发掘查询语言吧。首先咱们看一下返回文档的字段。默认状况下,是返回完整的JSON文档的。这能够经过 source来引用(搜索hits中的_source字段)。若是咱们不想返回完整的源文档,咱们能够指定返回的几个字段。

返回指定的account_number和balance两个 字段

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match_all": {}},  
  4.     "_source":["account_number", "balance"]  
  5. }  
上面的例子仅仅是简化了_source字段。它仍将会返回一个叫作_source的字段,可是仅仅包含account_number和balance来年改革字段

 

咱们看到了match_all查询是怎样匹配到全部的文档的。如今咱们介绍一种新的查询,叫作match查询,这能够当作是一个简单的字段搜索查询(好比对应于某个或某些特定字段的搜索)

查询account_number为44的文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match": {  
  4.        "account_number": 44  
  5.     }}  
  6. }  

 

搜索地址包含mill的文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match": {  
  4.        "address": "mill"  
  5.     }}  
  6. }  

 

搜索地址包含mill或者lane的文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {"match": {  
  4.        "address": "mill lane"  
  5.     }}  
  6. }  

下面这个例子是match的变体(match_phrase),它会去匹配短语“mill lane”:

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {  
  4.         "match_phrase": {  
  5.            "address": "mill lane"  
  6.         }  
  7.     }  
  8. }  

介绍一下布尔查询。布尔查询容许咱们利用布尔逻辑将较小的查询组合成较大的查询

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {  
  4.         "bool": {  
  5.             "must": [  
  6.                {"match": {  
  7.                   "address": "mill"  
  8.                }},  
  9.                {"match": {  
  10.                   "address": "lane"  
  11.                }}  
  12.             ]  
  13.         }  
  14.     }  
  15. }  

这个例子组合了两个match查询,这个组合查询返回必须包含“mill”和“lane”的全部的帐户

bool must语句指明了,对于一个文档,全部的查询都必须为真,这个文档才可以匹配成功

 

相反的,下面的例子组合了两个match查询,它返回的是地址中包含“mill”或者“lane”的全部的帐户

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {  
  4.         "bool": {  
  5.             "should": [  
  6.                {"match": {  
  7.                   "address": "mill"  
  8.                }},  
  9.                {"match": {  
  10.                   "address": "lane"  
  11.                }}  
  12.             ]  
  13.         }  
  14.     }  
  15. }  
bool should语句指明,对于一个文档,查询列表中,只要有一个查询匹配,那么这个文档就被当作是匹配的

 

下面这个例子组合了两个查询,它返回地址中既不包含“mill”,同时也不包含“lane”的全部的帐户信息

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {  
  4.         "bool": {  
  5.             "must_not": [  
  6.                {"match": {  
  7.                   "address": "mill"  
  8.                }},  
  9.                {"match": {  
  10.                   "address": "lane"  
  11.                }}  
  12.             ]  
  13.         }  
  14.     }  
  15. }  
在上面的例子中, bool must_not语句指明,对于一个文档,查询列表中的的全部查询都必须都不为真,这个文档才被认为是匹配的。
咱们能够在一个bool查询里一块儿使用must、should、must_not。此外,咱们能够将bool查询放到这样的bool语句中来模拟复杂的、多等级的布尔逻辑。


下面的列子搜索出,age=40而且state不等于PA的文档

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {  
  4.         "bool": {  
  5.             "must": [  
  6.                {"match": {  
  7.                   "age": 40  
  8.                }}  
  9.             ],  
  10.             "must_not": [  
  11.                {"match": {  
  12.                   "state": "PA"  
  13.                }}  
  14.             ]  
  15.         }  
  16.     }  
  17. }  

六、执行过滤器

在先前的章节中,咱们跳过了文档得分的细节(搜索结果中的_score字段)。这个得分是与咱们指定的搜索查询匹配程度的一个相对度量。得分越高,文档越相关,得分越低文档的相关度越低。


Elasticsearch中的全部的查询都会触发相关度得分的计算。对于那些咱们不须要相关度得分的场景下,Elasticsearch以过滤器的形式 提供了另外一种查询功能。过滤器在概念上相似于查询,可是它们有很是快的执行速度,这种快的执行速度主要有如下两个缘由

 

  • 过滤器不会计算相关度的得分,因此它们在计算上更快一些
  • 过滤器能够被缓存到内存中,这使得在重复的搜索查询上,其要比相应的查询快出许多

 

为了理解过滤器,咱们先来介绍“被过滤”的查询,这使得你能够将一个查询(像是match_all,match,bool等)和一个过滤器结合起来。

做为一个例子,咱们介绍一下范围过滤器,它容许咱们经过一个区间的值来过滤文档。这一般被用在数字和日期的过滤上。

使用一个被过滤的查询,其返回值是越在20000到30000之间(闭区间)的帐户。换句话说,咱们想要找到越大于等于20000而且小于等于30000的帐户

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "query": {  
  4.         "filtered": {  
  5.            "query": {"match_all": {}},  
  6.            "filter": {  
  7.                "range": {  
  8.                   "balance": {  
  9.                      "gte": 20000,  
  10.                      "lte": 30000  
  11.                   }  
  12.                }  
  13.            }  
  14.         }  
  15.     }  
  16. }  

分解上面的例子,被过滤的查询包含一个match_all查询(查询部分)和一个过滤器(filter部分)。咱们能够在查询部分中放入其余查询,在 filter部分放入其它过滤器。在上面的应用场景中,因为全部的在这个范围以内的文档都是平等的(或者说相关度都是同样的),没有一个文档比另外一个文档 更相关,因此这个时候使用范围过滤器就很是合适了。
一般状况下,要决定是使用过滤器仍是使用查询,你就须要问本身是否须要相关度得分。若是相关度是不重要的,使用过滤器,不然使用查询。若是你有SQL背 景,查询和过滤器在概念上相似于SELECT WHERE语句, although more so for filters than queries
除了match_all, match, bool,filtered和range查询,还有不少其它类型的查uxn/过滤器,咱们这里不会涉及。因为咱们已经对它们的工做原理有了基本的理解,将其应用到其它类型的查询、过滤器上也不是件难事。
 

六、执行聚合

聚合提供了分组并统计数据的能力。理解聚合的最简单的方式是将其粗略地等同为SQL的GROUP BY和SQL聚合函数。

在Elasticsearch中,你能够在一个响应中同时返回命中的数据和聚合结果。

你可使用简单的API同时运行查询和多个聚 合,并以一次返回,这避免了来回的网络通讯,这是很是强大和高效的。

按照state分组,按照州名的计数倒序排序

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "size": 0,  
  4.     "aggs":{  
  5.         "group_by_state":{  
  6.             "terms":{  
  7.                 "field":"state"  
  8.             }  
  9.         }  
  10.     }  
  11. }  
在SQL中,上面的聚合在概念上相似于:
   SELECT COUNT(*) from bank GROUP BY state ORDER BY COUNT(*) DESC
 

注意咱们将size设置成0,这样咱们就能够只看到聚合结果了,而不会显示命中的结果

这个例子计算了每一个州的帐户的平均余额(仍是按照帐户数量倒序排序的前10个州)

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "size": 0,  
  4.     "aggs":{  
  5.         "group_by_state":{  
  6.             "terms":{  
  7.                 "field":"state"  
  8.             },  
  9.             "aggs":{  
  10.                 "average_balance": {  
  11.                     "avg": {  
  12.                         "field": "balance"  
  13.                     }  
  14.                 }  
  15.             }  
  16.         }  
  17.     }  
  18. }  
注意,咱们把average_balance聚合嵌套在了group_by_state聚合之中。这是全部聚合的一个经常使用模式。你能够任意的聚合之中嵌套聚合,

这样你就能够从你的数据中抽取出想要的概述。

 

如今让咱们按照平均余额进行排序:

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "size": 0,  
  4.     "aggs":{  
  5.         "group_by_state":{  
  6.             "terms":{  
  7.                 "field":"state",  
  8.                 "order": {  
  9.                     "average_balance":"desc"  
  10.                 }  
  11.             },  
  12.             "aggs": {  
  13.                 "average_balance": {  
  14.                     "avg": {  
  15.                         "field": "balance"  
  16.                     }  
  17.                 }  
  18.             }  
  19.         }  
  20.     }  
  21. }  

使用年龄段(20-29,30-39,40-49)分组,而后在用性别分组,而后为每个年龄段的每个性别计算平均帐户余额

 

[html]  view plain  copy
  1. POST /bank/_search?pretty  
  2. {  
  3.     "size": 0,  
  4.     "aggs": {  
  5.         "group_by_age": {  
  6.             "range": {  
  7.                 "field": "age",  
  8.                 "ranges":[  
  9.                     {  
  10.                         "from":20, "to":30  
  11.                     },  
  12.                     {  
  13.                         "from":30, "to":40  
  14.                     },  
  15.                     {  
  16.                         "from":40, "to":50  
  17.                     }  
  18.                 ]  
  19.             },  
  20.              "aggs": {  
  21.                 "group_by_gender": {  
  22.                     "terms": {  
  23.                         "field": "gender"  
  24.                     },  
  25.                     "aggs": {  
  26.                         "average_balance": {  
  27.                             "avg": {  
  28.                                 "field": "balance"  
  29.                             }  
  30.                         }  
  31.                     }  
  32.                 }  
  33.             }  
  34.         }  
  35.     }  
  36. }  

不少关于聚合的细节,咱们没有涉及。若是你想作更进一步的实验,

http://www.elasticsearch.org/guide/en /elasticsearch/reference/current/search-aggregations.html是一个很是好的起点。

相关文章
相关标签/搜索