「javaes排序」java全排序
本篇文章给大家谈谈javaes排序,以及java全排序对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、es查询数据的工作原理是什么?
- 2、es使用与原理2 -- scoll技术,bouncing results,零停机重建索引等等
- 3、es java 怎么按指定字段排序
- 4、ES 深度分页scroll使用方式
es查询数据的工作原理是什么?
查询,GET某一条数据,写入了某个document,这个document会自动给你分配一个全局唯一的id,doc id,同时也是根据doc id进行hash路由到对应的primary shard上面去。也可以手动指定doc id,比如用订单id,用户id。
我们可以通过doc id来查询,会根据doc id进行hash,判断出来当时把doc id分配到了哪个shard上面去,从那个shard去查询
1)客户端发送请求到任意一个node,成为coordinate node(协调结点)
2)coordinate node进行hash后对document进行路由,将请求转发到对应的node,此时会使用round-robin 随机轮询算法 ,在primary shard以及其所有replica node中 随机选择一个 ,让读请求负载均衡
3)接收请求的node返回document给coordinate node
4)coordinate node返回document给客户端
es最强大的是做全文检索,就是比如你有三条数据
java真好玩儿啊
java好难学啊
j2ee特别牛
你根据java关键词来搜索,将包含java的document给搜索出来
es就会给你返回:java真好玩儿啊,java好难学啊
1)客户端发送请求到一个coordinate node
2)协调节点 将搜索请求转发到 所有的shard 对应的primary shard或replica shard
3)query phase: 每个shard将自己的搜索结果 (其实就是一些 doc id ), 返回给协调节点 ,由协调节点进行数据的 合并、排序、分页 等操作,产出最终结果
4)fetch phase:接着由 协调节点,根据doc id去各个节点上拉取实际的document数据 ,最终返回给客户端
尤其要注意的这里是先拿的id哟
es使用与原理2 -- scoll技术,bouncing results,零停机重建索引等等
默认情况下,是按照_score降序排序的,我们也可以定制排序规则
Elasticsearch使用的是 term frequency/inverse document frequency算法,简称为TF/IDF算法
Term frequency(TF): 搜索文本中的各个词条在field文本中出现了多少次,出现次数越多,就越相关
如:搜索请求:hello world
doc1:hello you, and world is very good
doc2:hello, how are you
doc1 肯定比doc2的评分高,因为hello world都在doc1中出现了。
Inverse document frequency(IDF): 搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,就越不相关
搜索请求:hello world
doc1:hello, today is very good
doc2:hi world, how are you
比如说,在index中有1万条document,hello这个单词在所有的document中,一共出现了1000次;world这个单词在所有的document中,一共出现了100次
那最终的结果肯定是 word的得分所占比更高
关于_score,ES还有一条规则。
Field-length norm:field长度,field越长,相关度越弱
搜索请求:hello world
doc1:{ "title": "hello article", "content": "babaaba 1万个单词" }
doc2:{ "title": "my article", "content": "blablabala 1万个单词,hi world" }
hello world在整个index中出现的次数是一样多的。最终 doc1得分更高
搜索的时候,要依靠倒排索引;排序的时候,需要依靠正排索引,看到每个document的每个field,然后进行排序,所谓的正排索引,其实就是doc values,doc values 也可以供排序,聚合,过滤等操作使用。doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高;如果内存不足够,os会将其写入磁盘上
正排索引如下:
倒排索引不可变的好处
想象一下有两个文档有同样值的时间戳字段,搜索结果用 timestamp 字段来排序。 由于搜索请求是在所有有效的分片副本间轮询的,那就有可能发生主分片处理请求时,这两个文档是一种顺序, 而副本分片处理请求时又是另一种顺序。
这就是所谓的 bouncing results 问题: 每次用户刷新页面,搜索结果表现是不同的顺序。 让同一个用户始终使用同一个分片,这样可以避免这种问题, 可以设置 preference 参数为一个特定的任意值比如用户会话ID来解决。
如
如果一次性要查出来比如10万条数据,那么性能会很差,此时一般会采取用scoll滚动查询,一批一批的查,直到所有数据都查询完处理完。
scoll,看起来挺像分页的,但是其实使用场景不一样。分页主要是用来一页一页搜索,给用户看的;scoll主要是用来一批一批检索数据,让系统进行处理的
使用scoll滚动搜索,可以先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来
scoll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的
采用基于_doc进行排序的方式,性能较高
每次发送scroll请求,我们还需要指定一个scoll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了
获得的结果会有一个scoll_id,下一次再发送scoll请求的时候,必须带上这个scoll_id
1 创建索引
2 修改索引
3 删除索引
lucene是没有type的概念的,在document中,实际上将type作为一个document的field来存储,即_type,es通过_type来进行type的过滤和筛选
一个index中的多个type,实际上是放在一起存储的,因此一个index下,不能有多个type重名,而类型或者其他设置不同的,因为那样是无法处理的
比如
底层存储是这样的
将类似结构的type放在一个index下,这些type应该有多个field是相同的
假如说,你将两个type的field完全不同,放在一个index下,那么就每条数据都d会有大量field在底层的lucene中是空值,会有严重的性能问题
1、定制dynamic策略
true:遇到陌生字段,就进行dynamic mapping
false:遇到陌生字段,就忽略
strict:遇到陌生字段,就报错
2、定制自己的dynamic mapping template(type level)
上面的设置是/my_index/my_type 的字段,如果是以_en结尾的,那么就自动映射为string类型
一个field的设置是不能被修改的,如果要修改一个Field,那么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api写入index中。
批量查询的时候,建议采用scroll api,并且采用多线程并发的方式来reindex数据,每次scoll就查询指定日期的一段数据,交给一个线程即可。
(1)一开始,依靠dynamic mapping,插入数据,但是不小心有些数据是2017-01-01这种日期格式的,所以title这种field被自动映射为了date类型,实际上业务认为它应该是string类型的
(2)当后期向索引中加入string类型的title值的时候,就会报错
(3)如果此时想修改title的类型,是不可能的
(4)此时,唯一的办法,就是进行reindex,也就是说,重新建立一个索引,将旧索引的数据查询出来,再导入新索引
(5)如果说旧索引的名字,是old_index,新索引的名字是new_index,终端java应用,已经在使用old_index在操作了,难道还要去停止java应用,修改使用的index为new_index,才重新启动java应用吗?这个过程中,就会导致java应用停机,可用性降低
(6)所以说,给java应用一个别名,这个别名是指向旧索引的,java应用先用着,java应用先用goods_index alias来操作,此时实际指向的是旧的my_index
(7)新建一个index,调整其title的类型为string
(8)使用scroll api将数据批量查询出来
(9)采用bulk api将scoll查出来的一批数据,批量写入新索引
(10)反复循环8~9,查询一批又一批的数据出来,采取bulk api将每一批数据批量写入新索引
(11)将goods_index alias切换到my_index_new上去,java应用会直接通过index别名使用新的索引中的数据,java应用程序不需要停机,零提交,高可用
(12)直接通过goods_index别名来查询,是否ok
现有流程的问题,每次都必须等待fsync将segment刷入磁盘,才能将segment打开供search使用,这样的话,从一个document写入,到它可以被搜索,可能会超过1分钟!!!这就不是近实时的搜索了!!!主要瓶颈在于fsync实际发生磁盘IO写数据进磁盘,是很耗时的。
es java 怎么按指定字段排序
可以使用SortBuilders..fieldSort(String field)函数指定字段,order指定升序还是降序
ES 深度分页scroll使用方式
我们知道ES对于from+size的个数是有限制的,二者之和不能超过1w。当所请求的数据总量大于1w时,可用scroll来代替from+size。
首次查询使用方式如下:
接下来的查询方式如下:
如果你对scroll取出的数据顺序没有要求的话,则可以对“_doc”进行排序,es对这种排序做了优化。使用方式如下:
如果你想通过slice并行分片查询的话,可以这样设置:
两个请求可以同时运行。但是这样做会有个缺陷,内存占用较大,且第一次查询很慢。因为查询是O(N)的复杂度且每个slice占用N个bits,N是shard的总文档数。之后缓存的数据将加快查询。
为了避免上述情况,可以选择一个doc_values做slice,但是必须要确保这个field有以下特性:
在第一次查询时,记录上一次查询的位置,在接下来的查询中获取到上次查询的位置,接着查询。
比如说将查询order by time offset 0 limit 100,改写成order by time where time0 limit 100,记录最后一个$time_max,接下来的查询order by time offset 100 limit 100,改写成order by time where time$time_max limit 100。如此往复,可以看出scroll是一个常量查询延迟和开销,并无什么副作用。
关于scroll 和search after的详细信息,请看 .
对应到java api中,可用addSort("_doc", SortOrder.ASC)代替。
关于javaes排序和java全排序的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。