elasticsearch应用场景,elasticsearch 应用
elasticsearch之七search搜索详解
query phase
一次请求要打到所有shard的一个replica/primary上去,如果每个shard都有多个replica,那么同时并发过来的搜索请求可以同时打到其他的replica上去
search的参数都是类似http请求头中的字符串参数提供搜索条件的。
GET [/index_name/type_name/]_search[?parameter_name=parameter_value...]
解释
took:耗费了几毫秒
timed_out:是否超时,这里是没有
_shards:到几个分片搜索,成功几个,跳过几个,失败几个。
hits.total:查询结果的数量,3个document
hits.max_score:score的含义,就是document对于一个search的相关度的匹配分数,越相关,就越匹配,分数也高
hits.hits:包含了匹配搜索的document的所有详细数据
与http请求传参类似
类比sql: select * from book where name like ’ %java%’ order by price desc
timeout参数:是超时时长定义。代表每个节点上的每个shard执行搜索时最多耗时多久。不会影响响应的正常返回。只会影响返回响应中的数据数量。
如:索引a中,有10亿数据。存储在5个shard中,假设每个shard中2亿数据,执行全数据搜索的时候,需要耗时1000毫秒。定义timeout为10毫秒,代表的是shard执行10毫秒,搜索出多少数据,直接返回。
GET /book/_search?timeout=10ms
全局设置:配置文件中设置 search.default_search_timeout:100ms。默认不超时。
所谓的multi-index就是从多个index中搜索数据。相对使用较少,只有在复合数据搜索的时候,可能出现。一般来说,如果真使用复合数据搜索,都会使用_all。
应用场景:生产环境log索引可以按照日期分开。
log_to_es_20190910
log_to_es_20190911
log_to_es_20180910
默认情况下,Elasticsearch搜索返回结果是10条数据。从第0条开始查询。
+/-搜索
+ :和不定义符号含义一样,就是搜索指定的字段中包含key words的数据
- : 与+符号含义相反,就是搜索指定的字段中不包含key words的数据
根据相关度评分倒排序,所以分页过深,协调节点会将大量数据聚合分析。
GET /book/_search?q=name:java
GET /book/_search?q=+name:java
GET /book/_search?q=-name:java
直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来。我们在进行中搜索的时候,难道是对document中的每一个field都进行一次搜索吗?不是的。
es中_all元数据。建立索引的时候,插入一条docunment,es会将所有的field值经行全量分词,把这些分词,放到_all field中。在搜索的时候,没有指定field,就在_all搜索。
举例
_all : jack,123@qq.com ,beijing 作为这一条document的_all field的值,同时进行分词后建立对应的倒排索引
DSL - Domain Specified Language , 特殊领域的语言。
请求参数是请求体传递的。在Elasticsearch中,请求体的字符集默认为UTF-8。
query string 后边的参数原来越多,搜索条件越来越复杂,不能满足需求。
DSL:Domain Specified Language,特定领域的语言
es特有的搜索语言,可在请求体中携带搜索条件,功能强大。
查询全部 GET /book/_search
排序 GET /book/_search?sort=price:desc
分页查询 GET /book/_search?size=10from=0
指定返回字段 GET /book/ _search? _source=name,studymodel
通过组合以上各种类型查询,实现复杂查询。
搜索需求:title必须包含elasticsearch,content可以包含elasticsearch也可以不包含,author_id必须不为111
初始数据:
搜索:
返回:
更复杂的搜索需求:
select * from test_index where name='tom' or (hired =true and (personality ='good' and rude != true ))
重新创建book索引
插入数据
搜索
relevance score算法,简单来说,就是计算出,一个索引中的文本,与搜索文本,他们之间的关联匹配程度。
Elasticsearch使用的是 term frequency/inverse document frequency算法,简称为TF/IDF算法。TF词频(Term Frequency),IDF逆向文件频率(Inverse Document Frequency)
Term frequency :搜索文本中的各个词条在field文本中出现了多少次,出现次数越多,就越相关。
举例:搜索请求:hello world
doc1 : hello you and me,and world is very good.
doc2 : hello,how are you
Inverse document frequency :搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,就越不相关.
举例:搜索请求:hello world
doc1 : hello ,today is very good
doc2 : hi world ,how are you
整个index中1亿条数据。hello的document 1000个,有world的document 有100个。
doc2 更相关
Field-length norm :field长度,field越长,相关度越弱
举例:搜索请求:hello world
doc1 : {"title":"hello article","content ":"balabalabal 1万个"}
doc2 : {"title":"my article","content ":"balabalabal 1万个,world"}
返回
搜索的时候,要依靠倒排索引;排序的时候,需要依靠正排索引,看到每个document的每个field,然后进行排序,所谓的正排索引,其实就是doc values
在建立索引的时候,一方面会建立倒排索引,以供搜索用;一方面会建立正排索引,也就是doc values,以供排序,聚合,过滤等操作使用
doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高;如果内存不足够,os会将其写入磁盘上
倒排索引
doc1: hello world you and me
doc2: hi, world, how are you
搜索时:
hello you -- hello, you
hello -- doc1
you -- doc1,doc2
doc1: hello world you and me
doc2: hi, world, how are you
sort by 出现问题
正排索引
doc1: { "name": "jack", "age": 27 }
doc2: { "name": "tom", "age": 30 }
一般搜索,如果不加from和size,就默认搜索前10条,按照_score排序
短语检索。要求查询条件必须和具体数据完全匹配才算搜索结果。其特征是:1-搜索条件不做任何分词解析;2-在搜索字段对应的倒排索引(正排索引)中进行精确匹配,不再是简单的全文检索。
决定了哪些shard会被用来执行搜索操作
_primary, _primary_first, _local, _only_node:xyz, _prefer_node:xyz, _shards:2,3
bouncing results问题,两个document排序,field值相同;不同的shard上,可能排序不同;每次请求轮询打到不同的replica shard上;每次页面上看到的搜索结果的排序都不一样。这就是bouncing result,也就是跳跃的结果。
搜索的时候,是轮询将搜索请求发送到每一个replica shard(primary shard),但是在不同的shard上,可能document的排序不同
解决方案就是将preference设置为一个字符串,比如说user_id,让每个user每次搜索的时候,都使用同一个replica shard去执行,就不会看到bouncing results了
主要就是限定在一定时间内,将部分获取到的数据直接返回,避免查询耗时过长
document文档路由,_id路由,routing=user_id,这样的话可以让同一个user对应的数据到一个shard上去
default:query_then_fetch
dfs_query_then_fetch,可以提升revelance sort精准度
ElasticSearch海量数据使用简述
应用场景当中经常会遇到模糊查询或多条件匹配查询,数据量较小的情况下通过简单的数据库模糊查询是可以解决的,但是对于数据量庞大的情况,数据库模糊查询就会出现性能问题。这种情况下的一种解决方案就是根据查询内容构建反向索引,借助搜索引擎进行查询,提升查询性能。
目前使用比较多的分布式搜索引擎是ElasticSearch。那么项目中如何使用ES?如何保证ES的数据更新?下面简单做个描述。
Elasticsearch使用可以简单分为两个阶段。数据初始化阶段、数据更新阶段。
数据初始化阶段。数据初始化常见的方式如下:
一、通过应用程序手动将数据库中的数据,调用ES接口API插入ES索引库中。
二、同过数据迁移工具将数据初始化到ES数据库。目前常用的ES同步工具有logstash-input-jdbc、DataX。通过同步迁移工具可以全量将数据库数据初始化到ES索引库中。
数据更新阶段。数据更新阶段常见的处理方式如下:
一、通过应用服务直接调用ES更新接口。这种方式实现比较简单但是对业务侵入性比较大。
二、对于实时性要求不高的可以采用定时任务监控数据表变化然后调用ES接口实现数据更新。
三、业务应用中通过发送消息异步更新数据。
四、通过DataX同步工具定时将修改的数据同步到ES库中。
上述是ElasticSearch使用的简单描述。使用的关键还是数据库与ES间的数据同步。能否用的好关键也是数据间的同步。
Elasticsearch——search搜索入门
Search执行的时候分为两个运行步骤:
相关性算分在shard与shard之间是相互独立的,也就意味着同一个Term的IDF等值在不同shard上是不同的,文档的相关性算分和它所处的shard相关,在文档数量不多时,会导致相关性算分严重不准的情况发生。
解决思路有两个:
es默认会采用相关性算分排序,用户可以通过设定sorting参数来自行设定排序规则
Fielddata VS DocValues
Fielddata默认是关闭的,可以通过如下api开启:
DocValues默认是启用的,可以在创建索引的时候关闭,如果后面要开启DocValues,需要做reindex操作。
可以通过该字段获取fielddata获取DocValues中储存的内容。
无条件搜索所有
解释 :
与http请求传参类似
默认情况下,es的timeout机制是关闭的。比如,如果你的搜索特别慢,每个shard都要花好几分钟才能查询出来所有的数据,那么你的搜索请求也会等待好几分钟才会返回。
我们有些应用系统对时间是非常敏感的,比如说电商网站,你不能让用户等10分钟,才能等到一次搜索请求的结果。
timeout机制 :指定每个shard只能在timeout时间范围内,将搜索到的部分数据(也可能是全部数据),直接返回给客户端,而不是等到所有的数据全部搜索出来以后再返回。确保一次搜索请求可以在用户指定的timeout时长内完成,为一些时间敏感的搜索应用提供良好的支持。
全局设置:配置文件中设置 search.default_search_timeout:100ms 。该设置不常用。
如何一次性搜索多个index和多个type下的数据
应用场景:生产环境log索引可以按照日期分开。
es提供了3种方式来解决分页与遍历的问题:
最常用的分页方案:
如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:
深度分页是一个经典问题:在数据分片存储的情况下,如何获取前1000条数据?
除了会遇到效率上的问题,还有一个无法解决的问题是es目前支持最大的skip值是max_result_window默认为10000,也就是说当from+size max_result_window时,es将返回错误。
解决方案:
问题描述:比如当客户线上的es数据出现问题,当分页到几百页的时候,es无法返回数据,此时为了恢复正常使用,我们可以采用紧急规避的方式,就是将max_result_window的值调至50000。
对于上面这种解决方案只是暂时解决问题,当es的使用越来越多时,数据量越来越大,深度分页的场景越来越复杂时,可以使用另一种分页方式scroll。
什么是deep paging
遍历文档集的api,以快照的方式来避免深度分页的问题。
直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来。我们在进行中搜索的时候,难道是对document中的每一个field都进行一次搜索吗?不是的。
es中all元数据。建立索引的时候,插入一条document,es会将所有的field值经行全量分词,把这些分词,放到all field中。在搜索的时候,没有指定field,就在_all搜索。
举例
_all : jack,123@qq.com ,beijing
参考: