Elasticsearch range 查询 ES 5.x TODO

在数据结构方面,新增了多个 range 字段类型,有什么用呢,如今你能够计算连续数据的交并集,能够是时间范围,也能够是数值范围。html

好比数据存放的是会议信息,航班有一个 range 字段,里面存的是会议的开始和结束时间,你经过对应的 range 查询能够很方便的查询,获得某个时间点哪些会议同时正在进行,那段时间会议室有空闲,能够预订等等。node

首先看看怎么定义吧,下面的这个例子, mapping 里面设置字段的 type 为 date_range 即表示一个时间的范围字段:es6

POST http://node1:9200/my_index
{
	"mappings":{
		"my_data":{
			"properties":{
				"name":{
					"type":"text"
				},
				"expected_attendees":{
					"type":"integer_range"
				},
				"time":{
					"type":"date_range",
					"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
				}
			}
		}
	}
}

POST http://node1:9200/my_index/my_data/1
{
	"name":"elasticon",
	"expected_attendees" : {
		"gte":5000,
		"lte":10000
	},
	"time":{
		"gte":"2017-03-03 20:20:20",
		"lte":"2017-04-04 04:04:04"
	}
}

POST http://node1:9200/my_index/_search
{
	"query":{
		"range":{
			"expected_attendees":{
				"gte":5000,
				"lte":10000,
				"relation":"within"
			}
		}
	}
}

POST http://node1:9200/my_index/_search
{
	"query":{
		"range":{
			"time":{
				"gte":"2017-03-03",
				"lte":"2017-04-05",
				"relation":"within"
			}
		}
	}
}

 

下一个特性值得介绍的就是 _all 字段的移除数据库

关于 _all 这个字段,场景其实就是为了知足快速检索的需求,当你不知道 mapping 里面有什么字段的状况下,你也可以自由的进行搜索, 因此为了实现这个需求,就有一个 _all 字段,它会把其余字段的内容都拷贝到这个字段里面,而后都当成 string 类型来处理,因此就存在了数据的冗余了,另外数字当成 string 也不能很好的压缩,而且都在 _all 一个字段,因此只能用一种分析器,在高亮的时候也是对这个 _all 字段进行的高亮,而不是真实的字段值,显示起来效果也很差。json

如今 query_string 和 simple_query_string 查询引入了一个 all_fields 模式,在没有指定字段的状况下,默承认以自动选择相关类型的字段分别执行查询,自动帮你展开,使用起来更加简单,另外, _all 字段将在 6.0 默认禁用且不可配置。数据结构

接下来,咱们看看搜索的高亮,咱们知道文本高亮是搜索体验的重要的一环,经过显示匹配结果的文本块并对关键字进行高亮可以让咱们对搜索结果有一个直观的认识。app

如今有一个新的高亮器: Unified Highlighter,你们可能会问,目前 ES 默认已经提供了 3 种不一样的高亮器,为何还会有一个新的轮子呢,由于以前的用法有点复杂 , 用户选择起来比较困难,新的 unified highlighter 目的就是简化高亮的使用,能够支持前面 3 种高亮类型的自动选择。curl

 

还有一个是 keyword 类型能够经过 normalizer 来进行标准化了, keyword 类型相比 text 类型就是不能分词,可是可能一样须要进行相应的标准化处理,好比统一转成小写,移除标点符号等等,使用方式和 analyzer 同样,好比下面的需求:机器学习

尽管设置了 keyword 类型,可是我一样是须要对文本进行处理的啊,用户不可能输入的彻底都是同样,错一个大小写,可能就查不出来了。elasticsearch

新的 normalizer 使用起来 很简单,和 analyzer 基本同样,专门用于 keyword 类型,以下:

POST http://node1:9200/my_index
{
	"settings":{
		"analysis":{
			"normalizer":{
				"my_normalizer":{
					"type":"custom",
					"char_filter":[],
					"filter":[
						"lowercase",
						"asciifolding"
					]
				}
			}
		}
	},
	"mappings":{
		"my_data":{
			"properties":{
				"foo":{
					"type":"keyword",
					"normalizer":"my_normalizer"
				}
			}
		}
	}
}

POST http://node1:9200/my_index/my_data/1
{
	"foo":"Zhangsan"
}

POST http://node1:9200/my_index/_search
{
	"query":{
		"match":{
			"foo":"ZHANGSAN"
		}
	}
}
-->
{
    "took": 25,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.2876821,
        "hits": [
            {
                "_index": "my_index",
                "_type": "my_data",
                "_id": "1",
                "_score": 0.2876821,
                "_source": {
                    "foo": "Zhangsan"
                }
            }
        ]
    }
}

另外一个就是 Multi-Word Synonyms,以前是不支持同义词中间有空格分割的,分词的时候会帮你切分开,搜索的时候不能正确处理词组这种同义词,以下面的场景。

这里有一组同义词,看起来没毛病。

有一个 phrase 查询,看起来也没毛病。

个人同义词过滤器就不对了,以下:

new is old ?这是什么状况?

由于分词的时候,把他们单个字拆开进行的同义处理。新的多词同义词采用 graph 方式处理,很好的解决了上面的问题。

同义词如今能够支持词组了,也就是说同义词若是是由多个词组成的,不会在分词的时候被傻傻的拆开,而是正确的处理。

还一个就是字段折叠( Field collapsing),这个特性比较有意思,你能够在搜索的时候,按某个字段做为维度进行去重,我这里写过一篇详细的博客,有兴趣的能够去看看:

http://elasticsearch.cn/article/132

Cancellable searches

ES 的搜索,对于一些耗时较长的查询,之前是没有办法取消的,除了干掉节点重来或者等待结束,没有办法,如今能够经过 ES 的任务管理机制来进行取消了, 5.3 已经提供。感兴趣的能够查看文档:

https://www.elastic.co/guide/en/Elasticsearch/reference/5.3/search.html#global-search-cancellation

Partitioned term aggs

ES 的聚合功能很强大吧, term aggs 相信也是你们经常使用的一种,若是遇到字段里面惟一 term 不少的场景,聚合起来不仅是慢,可能还无法正常运行。

如今 term aggs 提供了一种分区的概念,你能够对一个字段,分 n 次进行聚合,分而治之,有兴趣的能够看看文档:

https://www.elastic.co/guide/en/Elasticsearch/reference/5.3/search-aggregations-bucket-terms-aggregation.html#_filtering_values_with_partitions

另外,当你的集群变红的时候,你是否是手忙脚乱过,检查一大堆配置,访问一大堆接口来查看究竟是哪里出了问题。

如今方便了,新增的 /_cluster/allocation/explain 接口可以直接告诉你哪里出了问题:

Java REST Client 也有了更新, ES 以前提供了一个偏底层的 Java HTTP REST client,可是用起来太费劲,须要手动拼 JSON,如今, Java REST Client 分红了 Java High Level REST Client 和 Java Low Level REST Client, High Level 基于 Low Level 来实现,顾名思义,提供更多用户方便的接口调用, High Level REST Client 将提供和 Transport Client 相似的接口,不用手动去拼接 QueryDSL 的 JSON 了,目测在 5.5 版本提供。

据说大家有不少集群在跑?那你有没有用过 tribe node 来访问多个集群呢?, tribe-node 的工做方式是合并多个集群的元数据到一块儿,负责请求的转发。

不过 tribe-node 有几个问题,首先,他须要和各个集群的每一个节点创建链接,另外 tribe-node 的 配置的静态的,修改以后须要重启 tribe-node,每一个集群的元数据变化以后都须要进行合并,频繁的操做十分影响性能,而且集群的索引名称必须保证不能相同,同时,经过 tribe-node 只能只读,没法建立索引,再者,跨集群查询,会将全部的分片的数据都放到 tribe-node 上进行 reduce,若是分片不少,可能出现 OOM 等问题。

新引入的 cross-cluster 跨集群功能就是为了方便以一种更优雅的方式来替换掉 tribe-node。

先来上一张图,里面能够看到如何建立一个 cross-cluster。

能够看到,集群的任何节点都能执行跨集群操做,节点的元数据不须要频繁更新,集群间索引基于命名空间进行了隔离。

 

什么是命名空间?

GET sales:*,r_and_d:logs*/_search

{

"query": { … }

}

能够看到上面的 QueryDSL,正常的索引前面有 namespace:这样的前缀,这就是命名空间,也就是选择不一样的集群。

不只能够动态设置多个集群的访问,也不须要重启节点。集群间互相不受影响,更没有频繁的元数据的同步。

Kibana 可以彻底访问多个集群,且能建立索引和进行修改,具有完整访问权限。

跨集群访问只须要很轻量级的几个链接,不须要和每一个节点都创建链接,这个功能在 5.3 已经支持。

Batched Search Reduce Phases

另外,之前的搜索的 reduce 操做都是要等到把每一个分片的结果都拿到本地以后再作合并,因此为了不海量分片形成的资源大量占用的问题,以前是有一个最多 1000 个分片的软限制,也就是一个搜索最多只能检索 1000 个分片,如今新增的 batched search reduce phases 提供了分批进行 reduce 的行为,也就是不用所有拿到以后再作 reduce,而是拿到足够的分片(默认 512)以后就开始 作 reduce,而后拿到合并结果,释放相关的资源,继续获取其余的分片数据继续进行 reduce,这样就能处理海量的数据了,这个功能在 5.4 发布。

ES 6.0 展望

上面的这些功能基本会在 5.x 提供,而 es6.0 早已在路上了,有不少特性值得期待:

稀疏性 Doc Values 的支持,你们知道 es 的 doc values 是列式存储,文档的原始值都是存放在 doc values 里面的,而稀疏性是指,一个索引里面,文档的结构实际上是多样性的,可是郁闷的是只要一个文档有这个字段,其余全部的文档尽管没有这个字段,可也都要承担这个字段的开销,因此会存在磁盘空间的浪费,而这块的改进就是这个问题。

Index sorting,即在索引阶段的排序,即咱们查询的时候有时候会根据某个字段的值进行排序,好比时间、编号等等,若是在索引的时候提取排好序,那么搜索或聚合的时候就会很是快,相应的直接走预先排序好的索引就好了。固然索引的时候会要增长额外开销,适合不怎么变化的索引的场景。

顺序号的支持,每一个 es 的操做都有一个顺序编号,这个属于 es 内部的一个功能,能够提供:快速的分片副本恢复或同步;跨数据中心的节点恢复;甚至提供一个 Changes API 等等;

无缝滚动升级,使之可以从 5 的最后一个版本滚动升级到 6 的最后一个版本,不须要集群的完整重启。无缝滚动升级,也就是不用停服务,在线升级,补充一下。

 

什么是最后一个版本?

也就是 6 发布第一个版本,好比 6.0 的时候, 5 的对应的那个最后的发布的版本,好比 5.5,那么 5.5 能够直接滚动升级到 6.0。而且这两个版本咱们称为主要版本,他们还支持跨大版本的搜索。就是前面提到的 cross-cluster 特性,不一样的版本也能支持跨集群访问,以下:

下面还有一些:

Removal of types,在 6.0 里面,开始不支持一个 index 里面存在多个 type 了,全部的新的 index 都将只有一个虚拟的固定的 type: doc 来代替,基于 type 的 parent-child 关系将经过单独的 join 字段来实现, type 会在 7.0 完全移除。

Index-template inheritance,索引版本的继承,目前索引模板是全部匹配的都会合并,这样会形成索引模板有一些冲突问题, 6.0 将会只匹配一个,索引建立时也会进行验证。

Load aware shard routing, 基于负载的请求路由,目前的搜索请求是全节点轮询,那么性能最慢的节点每每会形成总体的延迟增长,新的实现方式将基于队列的耗费时间自动调节队列长度,负载高的节点的队列长度将减小,让其余节点分摊更多的压力,搜索和索引都将基于这种机制。

已经关闭的索引将也支持 replica 的自动处理,确保数据可靠。

X-Pack 的部分特性:

6.0 的部分特性预告就上面这些,我猜下面的特性你也一样感兴趣:

Elasticsearch-SQL

Elasticsearch 官方也要支持的 SQL 特性了。

默认提供了一个 CLI 工具,能够很方便的执行 SQL 查询,主要面向管理人员,提升常见操做的使用效率。

Kibana 里面也能够直接执行。

另外也兼容 JDBC 协议,现存的不少基于 JDBC 协议的各类 SQL 工具及 BI 工具都能直接把 es 当数据库来链接和进行数据分析。

使用 ES 变得更加轻量级,使用起来无依赖。

机器学习

去年 Elastic 收购了业界领先的行为数据分析厂商 Prelert,如今相关产品已经集成进入了 X-Pack 的机器学习模块,能够快速的实现基于 ES 数据的行为分析,借助 ES 的海量实时处理能力,采用非监督机器学习来识别异常行为。

上图是机器学习自动识别出来的异常数据点。

本文只是 ES 最近的众多改进的一部分,有关更详细的更新内容还以具体的版本发布记录为准。

ElasticStack 的其余开源项目也有不少有意思的改进和 feature,愿意了解更多的,能够关注咱们官方及社区的活动:

http://elasticsearch.cn/article/141

Q&A 

提问:可否说说 ES 是如何在 lucene 上实现分布式的?

这个不是一句话可以说清楚点,能够参考咱们的权威指南:

http://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/distributed-docs.html

提问:能否组织一些 ES 常见的复杂模型构建思路探讨这样的论题。主要是探讨如何实现与优化。我想这是在座的同窗都会有遇到的问题。

曾勇:复杂模型须要具体分析,能够参看咱们的权威指南:

http://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/modeling-your-data.html

提问:ES 与 solr 对比有什么优点?技术选型时如何考虑?

曾勇:网上的对比有不少,我就不一一赘述了,若是没有用过 solr,那建议直接使用 ES 吧,上手更快更简单。另外网上的优劣比较其实也要结合本身的实际场景,实践出真知。

问:请问下,若是我有 9G 的数据导入,如何导最快?以前 curl @xxx.txt 方式,可是数据文件一大 curl 标准格式导入就不行了。

曾勇:走 bulk 方式确定是最快的,txt 内容是什么格式呢,利用一些现存的工具,能够试试,好比 logstash,记得选择 bulk 模式。导入的时候,有不少参数也对速度有帮助,这个就要去看看索引的优化这块的内容了。

相关文章
相关标签/搜索