基本概念:html
索引Indexjava
es吧数据放到一个或者多个索引中,若是用关系型数据库模型对比,索引的地位与数据库实例(db)至关。索引存放和读取的基本单元是文档 (document)。es内部使用的是apache lucene实现的索引中数据的读写。(es被视为单独的一个索引,在lucene中不止一个,由于分布式中,es会用到分区shards和备份 replicas机制讲一个索引存储多份)。算法
文档document数据库
在es中,文档主要是存储实体。全部的es应用需求最后都须要统一建成一个检索模型:检索相关文档。apache
文档由一个或多个域,每一个域field由一个域名或多个值组成(有多个值的称为多值域)。json
在es中每一个文档均可能会有不一样的域field集合;也就是说文档是没有固定的模式和赞成的结构的。文档之间保持的类似性便可。api
在客户端角度来看,文档就是一个json对象。缓存
参数映射 全部的文档在存储以前都必须分析(analyze)流程,用户能够配置输入文本分解成token的方式:哪些token呗滤掉;或者其它的处理流程,好比去除html标签。服务器
文档类型(type)并发
每一个文档在es中都必须设定它的类型。文档类型使得同一个索引中在存储结构不一样文档时,只需根据文档类型就能够找到对应的参数映射信息,方便文档的存取。
节点Node
单独es服务器实例成为一个节点。
集群Cluster
集群可以存储超出单机容量的信息。因为目前单点就能够知足我们的需求,就不详细介绍了。
索引副本Replica
经过索引分片机制能够想es集群中导入超过单机容量的数据,客户端操做任意一个节点接口实现对集群数据的读写。(不作详细解释了)
时间之门gateway
在运行的过程当中,es会收到集群的状态,索引的参数等信息。这些呗存储在gateway中。
es背后核心理念:
es是构造极少数的几个极少数的概念之上的。
开箱急用。
天生集群。
自动容错。
扩展性强。
es工做原理:
启动过程:
当es节点启动后,会利用 多播(multicast)或单播(别问我什么是单播,多播,不必纠结这些)寻找病简历连接。如图:
在集群中,一个节点呗选举成主节点。这个节点扶着管理集群的状态,当集群的拓展结构改变时把索引分区分派到相对性的节点上。
在用户角度看节点在es中并无占据主要位置,这与其它系统是不一样的(数据库系统)。实际上用户并不须要知道哪一个节点是主节点;全部的操做需求 能够发到任意节点,es内部完成这些工做。必要时任意节点均可以并发的把查询自居分发到其余节点,而后合并各个节点返回的查询结果。最后返回用户一个完整 结果集。全部的这些工做不须要通过主节点转发(节点以前经过p2p的方式通信)。
在必要时,会进行恢复工做。这时主节点会去检查哪些分片可用,决定用哪些分片。处理完后,集群转入黄色状态。
这意味着集群能够处理搜索请求了。可是尚未火力全开(这主要是因为全部的主索引分区都已经分配好了,可是索引副本尚未)。接下来就是找到复 制好的分区,病设置成索引副本。当一个分区数量太少时,主节点会界定将缺乏的分区放到哪一个节点中,而且依照主分区建立副本。全部工做完成后,集群就会变成 绿色状态(标示全部的主分区的索引副本都已经分配完成了)。
探测是吧节点
在正常工做时,主节点会监控全部节点,查看各个节点是否工做正常。若是在指定的时间里,节点没法访问,就呗视为出现故障了,接下来错误处理程序 就会启动。集群须要均衡——因为该节点出现故障,分配到该节点的索引分片丢失。其实节点上相应的分区就会吧工做接管过来的这个过程能够经过配置知足用户需 求。
因为只是展现es的工做原理,就如下图三个节点的集群为例。集群中有一个主节点和两个数据节点。主节点想其余节点发送ping命令后等待回应。若是获得回应(实际上可能得不到恢复ping命令个数,取决于用户配置),改节点就会被移出集群。
与es进行通信
归根到底,最重要的是如何往es中添加数据以及如何查询数据。es提供了api,这些api都是基于rest风格。并且这些api很是容易与其余可以处理http的系统进行集群。
es为数据应该伴随在url中,或做为请求主体requst body。以一种json格式的文档发送给服务器。
es内部,节点之间通信解释用的先关javaapi。
重点来咯
索引数据
es提供了4中索引数据的方法。最简单的就是索引api。经过它能够将文档添加到指定的索引中去。好比curl工具。我能够经过以下命令建立一个新的文档
第二、3中方法,能够经过bulk API和UDP API批量添加文档。一般的bulk API采用HTTP协议,UDP bulk api采用非链接的数据包协议。UDP协议传输速度更快,但可靠性差点、最后一种是经过rivier插件。river运行在es集群的节点上,可以从外部 系统中获取数据。
有一点须要注意,索引数据的曹组只会发生在主分区上,而不会发生在分区副本上。若是索引数据的请求发送到节点上没有合适的分片或者分片副本,那么请求就会被转发到含有主分区的节点。
数据查询
查询api在es中有着很大的比重。经过query DSL(基于json,用于构造复杂的语言)
使用类型查询:简单关键词、短语、区间、布尔、模糊、跨度、通配符、地理位置等查询方式。
经过组合简单查询构造复杂的查询。
过滤文档,去除不符合标准的文档并且不影响打分排序。
查找给定文档的类似文档。
查找给定短语的搜索建议和查询短语修正。
经过faceting构建动态的导航和数据统计。
使用prospective search并且找到匹配写定文档的查询语句(prospective search一种推送方式。用户的查询语句存储在索引中,若是新的文档添加到索引中,就把文档关联到匹配的查询语句中。这种适合于新闻,博客等定时更新的场景)。
关于数据查询,其核心在于查询过程不是一个简单、单一的流程。经过这个过程分为两个阶段:查询阶段和结果汇总阶段。在查询分发阶段,会从各个分支中查询数据;在结果汇总阶段,会从各个分群上查询到结果进行合并,排序等其余处理过程,而后返回给用户。
用户能够经过指定搜索类型来控制查询的分发和汇总过程。
索引参数设置
es索引参数会自动配置
文档结构以及域类型会自动识别。固然es也容许用户自定修改默认配置。
好比,自行配置不少参数,好比经过mapping配置索引中的文档结构,设置分区shard和副本replica的个数,设置文本组件……
集群管理和监控
经过管理和监控部分的api,用户能够更改集群设置。好比调整节点发现机制或更改索引的分片策略。用户能够查看集群状态信息,或者每一个节点和索引和统计信息。集群监控的api很是普遍。
强大的用户查询语言DSL
if/idf打分公式
这个就是打分公式的真面目。若是只是为了调整查询语句之间的关联关系,用户没必要去理解它的原理。但只搜啊要知道它是如何工做的。
lucene概念上的打分公式
上面展现了布尔信息检索和向量空间信息检索模型的组合。(这个暂时忽略)
能够了解更多东西能够去这里
从es的角度看打分排序
最重要的是利用lucene构建起来的es容许用户修改默认的打分算法。但es不只仅是lucene的简单封装,由于es中,文档排序并不是彻底 依赖apache lucene的打分算法。es实现了多种不一样的查询类型,这些查询类型能够彻底依赖与文档的打分计算方式,es容许经过脚本定制文档的打分方式。
查询重写机制
若是你曾经使用过不少不一样的查询类型,好比前缀查询和通配符查询,从本质上,任何的查询均可以视为对多个关键词查询。查询重写(query rewrite),es对用户查询进行了重写,这样作为了保证性能。重写过程是吧lucene角度认为原始的、开销大的查询对象转变成一系列开销小的查询 对象的一个过程。
前缀查询:
例如:
我是知道全部字符以j开头的文档。这个需求很是简单,在client索引上运行
查询结果的重打分
有些场景对查询语句的结果文档进行从新打分是颇有必要的。从新打分的缘由可能各有相同。
其中一个缘由多是处于性能考虑,好比对整个有序的结果集进行重排序开销会很大,一般就会只对结果集进行重排序。
理解重打分
在es中,重打分是一个对限定数目的查询结果进行再次打分的一个过程。这意味着es会根据新的打分规则对结果的前n个文档从新进行一次排序
例
rescore query的结构:
重打分的参数
在查询语句的rescore对象中,用户能够添加以下参数
window_size提供了与N个文档的相关信息。用于执行分片上用于重打分的文档个数
query_weight默认1;原查询的打分会先乘以query_weight,而后与rescore的得分相加。
rescore_query_weight默认1,rescore的打分会先乘该值,在与原查询的得分相加。
rescore_mode默认tatal;在es0.90.0中引入用来指定重打分文档的打分方式。可选值:total,max,avg和multiply。
total:最终得分为原查询得分和rescore得分的和;
max,最终得分为原查询得分和rescore得分的最大值;
min,最终得分为原查询得分和rescore得分的最小值;
avg,最终得分为原查询得分和rescore得分的平均值;
multiply,两种查询的得分相乘。
例如设置recore_mode参数值为total,文档最终得分是
查询结果的排序
当给es发送查询命令时,返回的文档集合默认会按照计算出来的文档打分排序。这个一般是
用户但愿的:结果集中的第一个文档就是查询命令想要的文档。然而,有事咱们但愿改变这种排序
。
update API
当往索引中添加新的文档到索引中时,底层的lucene工具包会分析每一个域,生成token流
token流过滤后获得倒排索引。在这个过程当中输入文版中一系诶没必要要的信息会丢掉。
这些没必要要的信息多是一些特殊词的位置,一些停用的词或用同义词代替的词,或者词尾
。这也是为何没法对lucene中的文档进行修改,每次修改一个文档时,必须吧文档全部域 添加到索引中。es经过_source这个代理域来存储或检索文档中的真是数据。
当咱们想更新文档时,es会把数据放到_souce域中,而后作出修改,最后吧更新后的文档
添加到索引中。让然前提是_source域的这项特性必须生效。文档更新命令只能更新一个文档
查询命令的文档更新尚未出来。
更新:
使用update API建立或删除文档
update API不只能够修改某个域,同时也能操做整个文档。
upsert特性使得在定位到一个不存在的文档是,它会被建立爱你出来:
若是文档存在,该命令将重置year域中的值;不然会被建立。新的文档包含upset中定义的titile域。固然,上面的命令还有可使用脚本:
update还容许用户选择性的删除整个文档。
filters优化查询:
es支持多种类型的查询,可是查询那个匹配成功,哪一个应该呈现给用户,查询并非惟一的。es查询dsl容许用户使用绝大数查询都会有各自的标示。
过滤器(filters)和缓存
ES提供了特殊的缓存,filter cache来存储filters获得的结果集。此外,存储filters不须要太多的内存(它只保留一种信息,即哪些文档与filter相匹配),同时它能够与其余查询复用,极大的提升查询的性能。
例:
该命令查询获得知足以下条件的文档:name域值为joe同时值为1981。
用上面命令格式构建查询,查询对象会将全部的条件绑定到一块儿存储到缓存中;所以若是咱们查询人名相同但出生年份不一样的运动员,es没法重用上面查询命令中的任何信息。
所以,咱们须要优化下查询。因为1千我的可能有一千我的名,因此人名不太适合缓存起来;可是年份比较适合。所以咱们引入一个不一样的查询命令,将一个简单的query与一个filter结合起来。
咱们使用一个filtered类型的查询对象,查询对象将query元素与filter元素包含进去。第一次运行查询命令后,es会吧filter缓存起来,若是有查询用到同样的filter,就会直接用缓存。
并不是全部的filters都会被默认缓存起来
实际上es不会缓存全部的filters。这是由于部分filters会用到域数据缓存(field date cache)。该缓存通常用于按域值排序和faceting操做场景中。默认状况,以下filters不会呗缓存:
尽管最后三种不会用到域缓存,它们主要用于控制filters,所以不会被缓存,可是它们控制的filters在用时都已经缓存好了。
更改es缓存行为
es容许用户经过_cache和_cache_key属性自行开启或关闭filters功能。
假设咱们将关键词过滤器结果缓存起来,病给缓存项的key取名为year_1981_cache:
也能够用下面命令关闭过滤器缓存:
为了获取更多的控制权,咱们须要给缓存项的key取名。
好比,有些查询复用机很少,咱们但愿指定定时清理这些查询的缓存。若是不指定_cache_key。就只能清除整个过滤器缓存filter cacahe;反之,只需执行以下命令:
关键词查找过滤器
缓存和标准的查询并非所有内容。
索引定义了id信息,名字,用户购书的id列表。
一些测试数据:
假设咱们但愿展现某个用户购买的全部数据,以id为1的user为例。
term filter的工做原理
一个普通的es查询命令。它只是一个过滤查询,包含一个全量查询和一个terms过滤器。
只是查询命令中,terms过滤器使用了一种不一样的技巧——不明确指定某些term值,而是从索引中动态加载。
过滤器基于id域,由于咱们只须要id域就整合其它全部的属性。
index属性指明了加载terms的索引源。
type属性告诉es咱们的目标文档类型。
id属性指明咱们在执行索引文档的books域。
path属性告诉es应该从哪一个域中加载term。
terms lookup filter的缓存设置
filters和scope在es faceting的应用
faceting的结果只基于查询结果。如使用filters,那filters不会对facet用来的统计计算文档产生影响。
scope,能够扩展facet统计计算的文档范围。