「java中es使用」java中es怎么用
今天给各位分享java中es使用的知识,其中也会对java中es怎么用进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、es使用与原理4 -- phrase match ,slop近似匹配,搜索推荐等等
- 2、在Idea中如何用java代码与es做连接的项目
- 3、es使用与原理2 -- scoll技术,bouncing results,零停机重建索引等等
- 4、java 操作es多索引查询的时候,可不可以首先指定一个索引的查询条件,然后在进行多索引查询?
- 5、java中如何直接读取es语言
- 6、java实体类集合怎么保存es
es使用与原理4 -- phrase match ,slop近似匹配,搜索推荐等等
match query,只能搜索到包含java和spark的document,但是不知道java和spark是不是离的很近
包含java或包含spark,或包含java和spark的doc,都会被返回回来。我们其实并不知道哪个doc,java和spark距离的比较近。如果我们就是希望搜索java spark,中间不能插入任何其他的字符 或者指定中间只能隔num个字符,那这个时候match去做全文检索,能搞定我们的需求吗?答案是,搞不定。
两个需求:
1、java spark,就靠在一起,中间不能插入任何其他字符,就要搜索出来这种doc
2、java spark,但是要求,java和spark两个单词靠的越近,doc的分数越高,排名越靠前
phrase match 就是短语匹配,将短语作为一个整体去查找。
3、分词后的临时 position
从结果中,我们可以看出 hello的临时位置是0,world, java spark 的位置依次是 1,2,3
4、短语搜索的原理(近似搜索的原理也是这样的)
hello world, java spark doc1
hi, spark java doc2
hello doc1(0)
wolrd doc1(1)
java doc1(2) doc2(2)
spark doc1(3) doc2(1)
java spark -- match phrase
java spark -- java和spark
java -- doc1(2) doc2(2)
spark -- doc1(3) doc2(1)
要找到每个term都在的一个共有的那些doc,就是要求一个doc,必须包含每个term,才能拿出来继续计算
doc1 -- java和spark -- spark position恰巧比java大1 -- java的position是2,spark的position是3,恰好满足条件 ,doc1符合条件
doc2 -- java和spark -- java position是2,spark position是1,spark position比java position小1,而不是大1 -- 光是position就不满足,那么doc2不匹配
类似的 近似搜索原理也是这样的
slop的含义是什么? 搜索文本,中的几个term,要经过几次移动才能与一个document匹配,这个移动的次数,就是slop。简单的说就是 java 和 spark之间的距离 或者java和spark交换后的距离+2(这里的2是交换所需要的步数),slop搜索下,关键词离的越近,relevance score就会越高。
比如你搜索一个java spark,含有java,或者含有是spark,或者同时含有,并且 尽可能让包含java spark,或者是java和spark离的很近的doc,排在最前面,同时提供了召回率还兼顾了精准率。
直接用match_phrase短语搜索,会导致必须有term都在doc field中出现,而且距离在slop限定范围内,才能匹配上
此时可以用bool组合match query和match_phrase query一起,来实现上述效果
match -- 只要简单的匹配到了一个term,就可以理解将term对应的doc作为结果返回,扫描倒排索引,扫描到了就ok
phrase match -- 首先扫描到所有term的doc list; 找到包含所有term的doc list; 然后对每个doc都计算每个term的position,是否符合指定的范围; slop,需要进行复杂的运算,来判断能否通过slop移动,匹配一个doc
match query的性能比phrase match和proximity match(有slop)要高很多。因为后两者都要计算position的距离。
match query比phrase match的性能要高10倍,比proximity match的性能要高20倍。
默认情况下,match也许匹配了1000个doc,proximity match全都需要对每个doc进行一遍运算,判断能否slop移动匹配上,然后去贡献自己的分数
但是很多情况下,match出来也许1000个doc,其实用户大部分情况下是分页查询的,所以可能最多只会看前几页,比如一页是10条,最多也许就看5页,就是50条
proximity match只要对前50个doc进行slop移动去匹配,去贡献自己的分数即可,不需要对全部1000个doc都去进行计算和贡献分数
match:1000个doc,其实这时候每个doc都有一个分数了; proximity match,前50个doc,进行rescore,重打分,即可; 让前50个doc,term举例越近的,排在越前面
1、前缀搜索
C3D0-KD345
C3K5-DFG65
C4I8-UI365
C3 -- 上面这两个都搜索出来 -- 根据字符串的前缀去搜索
不用帖子的案例背景,因为比较简单,直接用自己手动建的新索引,给大家演示一下就可以了
2、前缀搜索的原理
prefix query不计算relevance score,与prefix filter唯一的区别就是,filter会cache bitset
扫描整个倒排索引,举例说明
前缀越短,要处理的doc越多,性能越差,尽可能用长前缀搜索
前缀搜索,它是怎么执行的?性能为什么差呢?
match
C3-D0-KD345
C3-K5-DFG65
C4-I8-UI365
全文检索
每个字符串都需要被分词
c3 doc1,doc2
d0
kd345
k5
dfg65
c4
i8
ui365
c3 -- 扫描倒排索引 -- 一旦扫描到c3,就可以停了,因为带c3的就2个doc,已经找到了 -- 没有必要继续去搜索其他的term了
match性能往往是很高的
如果前缀搜索那么 (前缀搜索是不分词的)
C3-D0-KD345
C3-K5-DFG65
C4-I8-UI365
c3 -- 先扫描到了C3-D0-KD345,很棒,找到了一个前缀带c3的字符串 -- 还是要继续搜索的,因为后面还有一个C3-K5-DFG65,也许还有其他很多的前缀带c3的字符串 -- 你扫描到了一个前缀匹配的term,
不能停,必须继续搜索 -- 直到扫描完整个的倒排索引,才能结束,所以prefix性能很差
3、通配符搜索
跟前缀搜索类似,功能更加强大
C3D0-KD345
C3K5-DFG65
C4I8-UI365
5字符-D任意个字符5
5?-*5:通配符去表达更加复杂的模糊搜索的语义
?:任意字符
*:0个或任意多个字符
性能一样差,必须扫描整个倒排索引,才ok
4、正则搜索
C[0-9].+
[0-9]:指定范围内的数字
[a-z]:指定范围内的字母
.:一个字符
+:前面的正则表达式可以出现一次或多次
wildcard和regexp,与prefix原理一致,都会扫描整个索引,性能很差
输入 hello w ,会联想到hello world,hello we,hello win,hello wind 等等
原理跟match_phrase类似,唯一的区别,就是把最后一个term作为前缀去搜索。
hello就是去进行match,搜索对应的doc
w,会作为前缀,去扫描整个倒排索引,找到所有w开头的doc
然后找到所有doc中,即包含hello,又包含w开头的字符的doc
根据你的slop去计算,看在slop范围内,能不能让hello w,正好跟doc中的hello和w开头的单词的position相匹配
也可以指定slop,但是只有最后一个term会作为前缀
max_expansions:指定prefix最多匹配多少个term,超过这个数量就不继续匹配了,限定性能
默认情况下,前缀要扫描所有的倒排索引中的term,去查找w打头的单词,但是这样性能太差。可以用max_expansions限定,w前缀最多匹配多少个term,就不再继续搜索倒排索引了。
尽量不要用,因为,最后一个前缀始终要去扫描大量的索引,性能可能会很差,可以使用ngram来实现
什么是ngram
quick,5种长度下的ngram
ngram length=1,q u i c k
ngram length=2,qu ui ic ck
ngram length=3,qui uic ick
ngram length=4,quic uick
ngram length=5,quick
什么是edge ngram
quick,首字母后进行ngram
q
qu
qui
quic
quick
-----------------------------------搜索推荐 未完。。。。。。。。。
在Idea中如何用java代码与es做连接的项目
下面介绍一下如何使用Idea连接TFS服务器,并提交变更的代码到TFS服务器。
一、连接TFS服务器,并下载代码
Figure 1
Figure 2
Figure 3 - 输入TFS服务器的地址,例如:
Figure 4 - 选择服务器代码库地址和本地地址
Figure 5 - 代码下载中
Figure 6 - 选择创建项目
Figure 7
Figure 8 - 继续, 后面几项都是Idea导入代码的界面,省略截屏
Figure 9 - 打开的项目
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写数据进磁盘,是很耗时的。
java 操作es多索引查询的时候,可不可以首先指定一个索引的查询条件,然后在进行多索引查询?
你建立的是联合索引,按照索引中字段顺序使用才会最大化的发挥索引的作用。
索引的建立不需要看主键有几个字段,而是看你的查询条件经常用到哪几列,
如果经常同时用到好几列,就可以在这几列上建联合索引,
如果查询条件经常都只是用到某一个字段,只需要在该字段上建一个单独索引
java中如何直接读取es语言
Elasticsearch不是java语言开发的,所以必须要通过api才能调用。你可以看看有没有第三方包可以直接操作。
java实体类集合怎么保存es
ava实体类集合保存es步骤如下。
1、通常ES存储数据是直接插入JSON数据。
2、在实际Java开发中一般定义数据接收对象是个实体对象,对ES进行新增修改操作时就需要新增保存。
关于java中es使用和java中es怎么用的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
发布于:2022-12-09,除非注明,否则均为
原创文章,转载请注明出处。