推广 热搜: 可以  搜索引擎  企业  page  个数  百度  使用  音视频  选择  父亲 

ElasticSearch 7.7.0 核心篇

   日期:2024-12-31     移动:http://ww.kub2b.com/mobile/quote/11251.html

它指把一段语句,拆分成单个的单词。同时对每个单词进行normalization (时态转换,单复数转换)处理,以提升recall召回率(搜索的时候,增加能够搜索到的结果的数量)。

1.1.1 分词器的主要构成

大部分的分词器都是有三块组成 预处理 、分词 、 过滤处理

  1. character filter:在一段文本进行分词之前,先进行预处理,比如说最常见的就是,过滤html标签(<span>hello<span> --> hello,& --> and(I&you --> I and you
  2. tokenizer:分词,hello you and me --> hello, you, and, me
  3. token filter:lowercase,stop word,synonymom,dogs --> dog,liked --> like,Tom --> tom,a/the/an --> 干掉,mother --> mom,small --> little

分词器,很重要,将一段文本进行各种处理,最后处理好的结果才会拿去建立倒排索引。

1.1.2 内置分词器的介绍

通过一个例句简单了解下

例句:Set the shape to semi-transparent by calling set_trans(5)

  1. standard analyzer:set, the, shape, to, semi, transparent, by, calling, set_trans, 5(默认的是standard
  2. simple analyzer:set, the, shape, to, semi, transparent, by, calling, set, trans
  3. whitespace analyzer:Set, the, shape, to, semi-transparent, by, calling, set_trans(5)
  4. language analyzer(特定的语言的分词器,比如说,english,英语分词器:set, shape, semi, transpar, call, set_tran, 5

通过一个例子体会下

doc1:I really liked my small dogs, and I think my mom also liked them.

doc2:He never liked any dogs, so I hope that my mom will not expect me to liked him.

1.2.1 简单的倒排索引

word

doc1

doc2

*

*

really

*

 

liked

*

*

my

*

*

small

*

 

dogs

*

 

and

*

 

think

*

 

mom

*

 

also

*

 

them

*

 

He

 

*

never

 

*

any

 

*

so

 

*

hope

 

*

that

 

*

will

 

*

not

 

*

expect

 

*

me

 

*

to  

 

*

him

 

*

搜索  mother like little dog,不可能有任何结果。因为我们分词后是这样的:mother  like  little  dog

所以我们还需要 normalization 下,建立倒排索引的时候,也就是说对拆分出的各个单词进行相应的处理,以提升后面搜索的时候能够搜索到相关联的文档的概率。

因此我们要进行 :时态的转换,单复数的转换,同义词的转换,大小写的转换

mom —> mother

liked —> like

small —> little

dogs —> dog

1.2.2 normalization 后的倒排索引

word

doc1

doc2

normalization

*

*

 

really

*

 

 

liked

*

*

liked --> like

my

*

*

 

small

*

 

 small --> little

dogs

*

 

dogs --> dogand

*

 

 

think

*

 

 

mom

*

 

 

also

*

 

 

them

*

 

 

He

 

*

 

never

 

*

 

any

 

*

 

so

 

*

 

hope

 

*

 

that

 

*

 

will

 

*

 

not

 

*

 

expect

 

*

 

me

 

*

 

to  

 

*

 

him

 

*

 

这样我们就能搜索到相关的文档了。

1.2.3 倒排索引的数据结构

倒排索引他主要是适合用于进行搜索的,因此倒排索引的结构是

  1. 包含这个关键词的doc list
  2. 包含这个关键词的所有doc的数量:IDF(inverse document frequency
  3. 这个关键词在每个doc中出现的次数:TF(term frequency
  4. 这个关键词在这个doc中的次序
  5. 每个doc的长度:length norm
  6. 包含这个关键词的所有doc的平均长度

倒排索引不可变的好处

(1)不需要锁,提升并发能力,避免锁的问题

(2)数据不变,一直保存在os cache中,只要cache内存足够

(3)filter cache一直驻留在内存,因为数据不变

(4)可以压缩,节省cpu和io开销

倒排索引不可变的坏处

每次都要重新构建整个索引

ES为了实现进实时搜索,在写入doc 时利用了Buffer(内存),OS Cache(系统缓存,属于系统内存的一部分),Disk(磁盘)三种存储方式,尽可能的提升搜索的能力。ES的底层是lucene实现的,而在luncene中一个index会被分为若干个数据段(segment),每一个segment都会存放index的部分doc。从流程上讲,ES会先把一个index中的doc分散存储在若干个shard(指的是主分片)上,在每个shard中又使用若干个segment来存储具体的数据。

1.3.1 写入原理

ES写入数据的流程大致如下:

 

                                                   注意该图是简化版的写入流程

客户端发起请求(增、删、改)到ES中。

ES将本次请求要操作的doc写入到buffer中。ES为了保证搜索的近实时(Near Real Time 简称 NRT),默认每秒刷新一次buffer,这个刷新时间间隔可以手动修改,也可以通过命令触发buffer的刷新。建议刷新时间间隔设置在1秒左右,好处使在服务器宕机后,只会丢失1秒左右的数据。当然了,如果Buffer中没有任何数据,则不会执行refresh操作(总不能创建空文件吧)

 

1.3.2 可靠写入原理

ES可靠写入数据的流程大致如下:

 

ES在将doc写入到buffer的同时,也会将内容写入到translog文件中,这份文件存在的意义在于即便ES宕机了,也能尽可能的减少丢失的数据(简单来说,就是把translog中的记录重新执行一遍)。当然translog也不能保证数据绝对不丢失。由于translog存储在磁盘Disk(日志文件)中,因此为了提高访问效率,ES与translog文件之间会建立并保持一个长连接(不然每次访问都要获取和释放文件流)。

translog 如何恢复数据

在系统重启后,ES会重新读取磁盘Disk中保存的数据(一份份的 index segment文件)到系统缓存中,然后接着读取translog中的操作日志并逐条执行,以此来达到恢复数据的目的。

注意translog 文件的持久有两种方式默认是per request fsync 每次客户端写入请求被持久化以后,才会回应200(同时后台也会异步每5s持久化一次)

这种安全保障是以牺牲写入吞吐量来换取的(这也是为什么升级到5.x后会发现写入吞吐量下降,所以应该怎么选择要看业务需求。 由于一般线上会配置1个或更多复制片,即使采用异步fsync模式,当某个结点真的掉电translog丢失了部分数据的时候,复制片会被promote成主片,而它的数据是完整的,数据依然安全。 只有同一个shard主副分片所在机器同时掉电才可能丢失部分数据。

所以在日志应用场景,一般用户允许极端情况丢失数据,我们就采用async方式持久化translog,可以换取巨大的吞吐量提升。 而在某些业务搜索的场景,一般数据量级很小,如果对于写入速度要求不高,那么可以采用默认的per request方式,保证极端情况下的数据安全。

 

1.3.3  translog flush 原理

随着时间的推移,translog文件会不断的增大,在内存中积压的数量众多的index segment file的文件流也在不断的增大,OS Cache中积压的数据也越来越大,当translog文件大到一定程度或默认30分钟执行一次,ES会自动触发commit操作(又叫flush操作)。commit操作的具体内容有:

  1. 将buffer中的数据刷新到一个新的index segment中 ,index segment写入到OS Cache并打开index segment为搜索提供服务
  2. 执行一个commit point操作,将OS Cache中所有的index segment标识记录在这个commit point中,并持久化到系统磁盘Disk
  3. commit point操作会触发fsync操作(file sync),将内存中已经写入数据的index segment落盘(强制刷新)到Disk磁盘上,持久化成文件。
  4. 清空本次持久化的index segment对应在translog中的日志。

1.3.3  segment Merge 原理

按照上述的流程来看,每1秒会生成一个index segment文件,每30分钟会将index segment文件流持久化到磁盘,照这样来看,磁盘中的index segment文件会非常多,从而需要处于开启状态的index segment也非常多,在执行搜索操作时,找到数据对应的index segment就会比较费时了。但不用担心,因为ES会定期进行Merge操作。

merge的大致流程如下:

  1. ES会选取一些大小相近的segment文件流,合并成一个大的segment文件流(注意: segment可能是尚未持久化到磁盘的segment file,也可能是已经持久化到磁盘的segment file,不管是哪种状态的segment file,此时它们都在OS Cache中)。
  2. 执行commit操作,在Disk中记录commit point,这个commit point不仅包含新增的segment,还包含需要被删除的segment(标记删除)。
  3. commit操作结束后,ES会将merge后的segment文件重新打开,为搜索提供服务,而那些需要被删除的segment文件则进行关闭并物理删除。

ES为了保证数据的近实时搜索能力,不会直接在物理磁盘中删除目标数据所在的segment文件,而是先把待删除的数据放入一个.del文件中,在执行segment merge操作时,通过参考.del文件,忽略掉已被删除的数据,最终把大量的segment file合并成一个或几个segment file。

在buffer数据写入到segment的同时,会生成一个.del文件专门记录哪一个index segment中哪一条document是deleted状态(在merge后,这个.del文件会被更新)。因此ES搜索时,如果在多个index segment中查到了不同版本(version)的相同id值的doc时,会根据.del文件中的记录来继续过滤,保证搜索结果的唯一性和正确性(比如segment1中包含一条document version=1,对应新增状态;而segment2中包含相同id的document version=2,对应更新状态。由于后者的版本号更新,因此在.del中,version1被视作旧document,会被标记成deleted状态,从而在搜索时就会得到segment2中包含的version=2的数据了)。

假设客户端请求查询_id=10的数据。

请求发送到ES集群中的任意节点,此时该节点成为本次请求的协调节点。协调节点默认根据数据的_id作为routing(可以手动指定,只需要在查询时增加_routing参数即可)进行hash算法,Hash(routing) % number_of_shards,假设计算出目标数据存放的shard的下标是3。接着,协调节点请求master节点,获取下标为3的shard所在节点的访问路径、端口等信息,并将查询请求转发至目标节点中。(注意:显然下标为3的shard不一定只有一个,有可能存在一个primary shard和多个replica shard的场景,至于到底把请求发送到哪一个shard上,取决于随机轮寻算法round-robin)

目标节点在目标分片内根据_id轻松的查询到数据,并将数据回传给协调节点。

协调节点将数据返回给客户端。

假设客户端请求查询某一个field的值为"hello java"。则请求发送到ES集群中的任意节点,此时该节点成为本次请求的协调节点。此时协调节点不知道目标数据到底存放在哪个节点的那个分片上,因此协调节点会把请求转发到ES集群当中的每一个节点中。

1.5.1 query phase 搜索数据原理

搜索请求发送到某一个coordinate node,构构建一个priority queue,长度以paging操作from和size为准,默认为10,coordinate node将请求转发到所有shard,每个shard本地搜索,并构建一个本地的priority queue,各个shard将自己的priority queue返回给coordinate node,并构建一个全局的priority queue。

1.5.2 fetch phase 拉取数据原理

(1)coordinate node构建完priority queue之后,就发送mget请求去所有shard上获取对应的document

(2)各个shard将document返回给coordinate node

(3)coordinate node将合并后的document结果返回给client客户端

一般搜索,如果不加from和size,就默认搜索前10条,按照_score排序

buffer和尚未写入系统缓存的index segment(就是一段倒排索引)存储在堆内存,受jvm参数控制。

系统缓存 OScache在这里可以被看做是"文件系统缓存",用于缓存打开后的segment file(段文件),存储在非堆内存,受操作系统控制。

非堆内存越大,能够打开并缓存的segment file(段文件)就越多,搜索和聚合时,能够直接从内存中获取的热数据也就越多(不需要通过IO,在磁盘中找到尚未打开的segment file,读取文件内容)。

搜索数据时,首先在OS Cache中进行搜索,如果找不到数据,则在磁盘中找到对应的index segment文件并打开,读取数据至堆内存中,接着,在堆内存中对数据进行聚合、排序等操作,最后把数据返回给协调节点,最终交给调用方。此外,新读取到堆内存的segment file会被Lucense缓存至非堆内存中。

两个document排序,field值相同;不同的shard上,可能排序不同;每次请求轮询打到不同的shard shard上;每次页面上看到的搜索结果的排序都不一样。这就是bouncing result,也就是跳跃的结果。

_primary, _primary_first, _local, _only_node:xyz, _prefer_node:xyz, _shards:2,3

解决方案就是将preference设置为一个字符串,比如说user_id,让每个user每次搜索的时候,都使用同一个replica shard去执行,就不会看到bouncing results了。

简单来说,就是计算出,一个索引中的文本,与搜索文本,他们之间的关联匹配程度

Elasticsearch使用的是 Term Frequency/Inverse document Frequency算法,简称为TF/IDF算法

1.14.1 Term Frequency(TF算法)

搜索文本中的各个词条在field文本中出现了多少次,出现次数越多,就越相关

搜索请求:hello world

doc1:hello you, and world is very good

doc2:hello, how are you

1.14.2 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次

doc2更相关

1.14.2 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更相关,title field更短

ES存储document时,会根据数据对应的field类型建立对应的索引。通常来说只创建倒排索引,倒排索引是为了搜索而存在的,但如果对数据进行排序、聚合、过滤等操作时,再使用倒排索引就明显不适合了。这个时候就需要在ES中创建正排索引(doc values)。doc values保存在磁盘中,如果OS Cache系统缓存的空间足够大,ES会缓存doc values,因此性能还是很不错的。

问: 为什么说倒排索引不适合做聚合、排序等操作

 

为remark字段创建倒排索引:

分词

doc1

doc2

java

*

*

开发

*

 

架构

 

*

工程师

*

*

如果在倒排索引的基础上进行聚合,那么到底是根据java进行聚合呢、还是根据开发或者架构来聚合呢?不难发现,用哪一个都不合适。排序也是如此。倒排索引因分词得到了许多好处,但也因此留下了弊端。

所以,为了应对这种不需要分词的需求和场景,ES设计了正排索引Doc values。Doc values不会对字段作任何分词处理,皆保留原值。

正排索引的大致结构如下:

doc values

values

doc1

java开发工程师

doc2

java架构工程师

ES会根据document中每个字段是否分词,有选择性的实现字段对应的倒排索引或正排索引(Doc values)。

比如,如果字段类型为keyword,long,date,那么这些类型修饰的字段一定会有正排索引(Doc values)。

比如,如果字段类型为text,则只会有倒排索引,不会主动创建正排索引。

如果想在同一个字段中,既实现正排索引,又实现倒排索引,只需要使用fielddata即可,实现方式如下(我们前面讲解过1.13 ):

若遇到聚合、排序等需求时,ES使用test_field.keyword,若遇到搜索需求时,ES使用test_field。

 
 
 

关于对索引的操作

2.1.1 查询 创建 删除 index

查询 GET /index

创建

 

删除 DELETe /index

2.1.2  修改 index settings(number_of_replicas)

 
 

1、默认的分词器

standard

standard tokenizer:以单词边界进行切分

standard token filter:什么都不做

lowercase token filter:将所有字母转换为小写

stop token filer(默认被禁用:移除停用词,比如a the it等等

2、修改分词器的设置

启用english停用词token filter

 

测试

 

3、定制化自己的分词器

 

测试

 
 

一个field的设置是不能被修改的,如果要修改一个Field,那么应该重新按照新的mapping,建立一个index,然后将数据批量查询出来,重新用bulk api写入index中。批量查询的时候,建议采用scroll api,并且采用多线程并发的方式来reindex数据,每次scoll就查询指定日期的一段数据,交给一个线程即可。

场景模拟

     依靠dynamic mapping 插入数据 但是不小心有些数据是2017-01-01这种日期格式的,所以title这种field被自动映射为了date类型,实际上它应该是string类型的。

 

查看mapping

 

当后期向索引中加入string类型的title值的时候,就会报错

 

结果报错:failed to parse field [title] of type [date] in document with id '2'. Preview of field's value: 'my first article'"

如果此时想修改title的类型,是不可能的。此时,唯一的办法,就是进行reindex,也就是说,重新建立一个索引,将旧索引的数据查询出来,再导入新索引。

如果说旧索引的名字,是old_index,新索引的名字是new_index,终端java应用,已经在使用old_index在操作了,难道还要去停止java应用,修改使用的index为new_index,才重新启动java应用吗?这个过程中,就会导致java应用停机,可用性降低。

隐藏,给java应用一个别名,这个别名是指向旧索引的,java应用先用着,java应用先用goods_index alias来操作,此时实际指向的是旧的my_index。

1.旧索引给个别名              PUT /qq_index/_alias/goods_index

2.新建一个index,调整其title的类型为string

 

使用scroll api将数据批量查询出来

 

查询结果

 

采用bulk api将scoll查出来的一批数据,批量写入新索引

 

反复查询一批又一批的数据出来,采取bulk api将每一批数据批量写入新索引,将goods_index alias切换到my_index_new上去,java应用会直接通过index别名使用新的索引中的数据,java应用程序不需要停机,零提交,高可用

 

直接通过goods_index别名来查询,是否ok

GET /goods_index/_search

 mapping 自动或手动为index中的type建立的一种数据结构和相关配置,简称为mapping

3.1.1 初始化数据

 

3.1.2 mapping 解析

GET /website/_mapping

 

由查询结果得知,dynamic mapping自动为我们建立index,创建type,以及type对应的mapping,mapping中包含了每个field对应的数据类型。

  1.  往es里面直接插入数据,es会自动建立索引,同时建立type以及对应的mapping
  2.  mapping中就自动定义了每个field的数据类型
  3.  不同的数据类型(比如说text和date,可能有的是exact value(建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的,有的是full text(会经历各种各样的处理,然后分词,再normaliztion(时态转换,同义词转换,大小写转换,才会建立到倒排索引中(这个在后面搜索的时候就能体会到
  4. exact value和full text类型的field就决定了,搜索的时候,对field (exact value 或者full text field)搜索行为是不一样的,会跟建立倒排索引的行为保持一致;比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索
  5. 最后我们可以用es的dynamic mapping,让其自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,自己对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等

mapping它是index的type的元数据,每个type都有一个自己的mapping,它决定了数据类型,建立倒排索引的行为,还有进行搜索的行为。(后面我们在1.7.3 搜索的时候会讲到

9个基本类型 keyword  byte,short,integer,long  float,double  boolean  date

  1. true or false --> boolean
  2. 123  --> long
  3. 123.45  --> double
  4. 2017-01-01 --> date
  5. "hello world" --> keyword/text

只能创建index时手动建立mapping,或者新增field mapping,但是不能update field mapping

手动创建  PUT /website

 

我们尝试修改field mapping ,我们前面说过不能修改。PUT /website

 

结果是不行的

但是我们可以新增field mapping

PUT /website/_mapping

 

测试 mapping 分词   GET /website/_analyze

 

 

分词为  my  dogs  GET website/_analyze

 

这个就不会分词

true:遇到陌生字段,就进行dynamic mapping

false:遇到陌生字段,就忽略

strict:遇到陌生字段,就报错

 

测试(错误的

 

遇到陌生字段,就报错:mapping set to strict, dynamic introduction of [content] within [_doc] is not allowed

测试(正确的

 

date_detection

默认会按照一定格式识别date,比如yyyy-MM-dd。但是如果某个field先过来一个2017-01-01的值,就会被自动dynamic mapping成date,后面如果再来一个"hello world"之类的值,就会报错。可以手动关闭某个type的date_detection,如果有需要,自己手动指定某个field为date类型。

 

定制自己的dynamic mapping template(type level

插入模板

 

插入数据

 

搜索验证  GET /dd_index/_search?q=is

查询结果只能查询到1。

title没有匹配到任何的dynamic模板,默认就是standard分词器,不会过滤停用词,is会进入倒排索引,用is来搜索是可以搜索到的。

title_en匹配到了dynamic模板,就是english分词器,会过滤停用词,is这种停用词就会被过滤掉,用is来搜索就搜索不到了。

4.1.1 解析搜索结果的含义&timeout机制。

GET /_search

 
  1. took:整个搜索请求花费了多少毫秒
  2. hits.total:本次搜索,返回了几条结果
  3. hits.max_score:本次搜索的所有结果中,最大的相关度分数是多少,越相关,_score分数越大,排位越靠前
  4. hits.hits:他是是个数据的数组包含前10条,默认查询前10条数据,_score降序排序
  5. shards:shards fail的条件(primary和replica全部挂掉,不影响其他shard。默认情况下来说,一个搜索请求,会打到一个index的所有primary shard上去,包括replica 上。
  6. timeout:默认无timeout(即查多久,就得等多久,latency平衡completeness,手动指定timeout,timeout查询执行机制 timeout=10ms,timeout=1s,timeout=1m

一般用在那种特别复杂庞大的搜索下,比如你一下子写了上百行的搜索,这个时候可以先用validate api去验证一下,搜索是否合法。

比如一个有错的 请求

 

他会提示错误

 
 

4.3.1 精确匹配 exact value

搜索的时候,搜索文本必须是全匹配才能搜索到

4.3.2 全文检索 full text

他不是单纯的只是匹配完整的一个值,而是可以对搜索文本进行拆分词语后(分词)进行匹配,也可以通过缩写、时态、大小写、同义词等进行匹配。

4.4.1 query string语法

url?q=field:search content

GET /test_index/test_type/_search?q=test_field:test

GET /test_index/test_type/_search?q=+test_field:test   (必须包含test,可以省略

GET /test_index/test_type/_search?q=-test_field:test   (必须不包含test

4.4.2 _all metadata的原理和作用

搜索document 中所有的field

GET /test_index/test_type/_search?q=test

es中的_all元数据,在建立索引的时候,我们插入一条document,它里面包含了多个field,此时,es会自动将多个field的值,全部用字符串的方式串联起来,变成一个长的字符串,作为_all field的值,同时建立索引,后面如果在搜索的时候,没有对某个field指定搜索,就默认搜索_all field,其中是包含了所有field的值。

生产环境不使用

4.4.3 _all & 指定field 查询结果不一致

我们还是查询前面初始化好的数据

  1. GET /website/article/_search?q=2017                           3条结果              
  2. GET /website/article/_search?q=2017-01-01                  3条结果
  3. GET /website/article/_search?q=post_date:2017-01-01   1条结果
  4. GET /website/article/_search?q=post_date:2017             1条结果

搜索结果为什么不一致,因为es自动建立mapping的时候,设置了不同的field不同的data type。不同的data type的分词、搜索等行为是不一样的。所以出现了_all field和post_date field的搜索表现完全不一样。

GET /_search?q=2017 搜索的是_all field。document所有的field都会拼接成一个大串,进行分词

2017-01-02 my second article this is my second article in this website 11400

分词

doc1

doc2

doc3

2017

*

*

*

01

*

*

*

02

 

*

 

03

 

 

*

自然会搜索到3个docuemnt

GET /_search?q=2017-01-01

_all,2017-01-01,query string会用跟建立倒排索引一样的分词器去进行分词 2017 01 01 所以也能查询三个

GET /_search?q=post_date:2017-01-01

date 会作为exact value去建立索引

分词

doc1

doc2

doc3

2017-01-01

*

 

 

2017-01-02

 

*

 

2017-01-03

 

 

*

所以只能查询到一个。

分页使用场景很常见,我们看看怎么使用。

size :每页几条,from :开始点。

例如

GET /_search?size=10

GET /_search?size=10&from=0

GET /_search?size=10&from=20

4.5.1 分页语法

查询测试数据

GET /test_index/test_type/_search

返回结果

 

5条数据分成3页,每一页是2条数据,来实验一下这个分页搜索的效果

GET /test_index/test_type/_search?from=0&size=2

其结果是

第一页 from= 0 ,结果是2条

第二页 from= 2 ,结果是2条

第三页 from= 4 ,结果是1条

4.5.2 deep paging 原理

深度分页,就是翻页的数据很大,即也就是很深,如果没有优化处理,会引发相关性能问题,甚至服务不可用。

4.5.3 scroll 滚动分页解决深度分页

使用scroll滚动搜索,可以先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来。

  1. scroll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的,采用基于_doc进行排序的方式,性能较高。
  2. 每次发送scroll请求,我们还需要指定一个scroll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以。
  3.  

    获得的结果会有一个scoll_id,下一次再发送scoll请求的时候,必须带上这个scoll_id

 
 

4.6.1 初始化数据

 

搜索请求:年龄必须大于等于30,同时join_date必须是2016-01-01

4.6.2  filter与query初体验

 
  1. filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响
  2. query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序
  3. 一般来说,如果你是在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter

4.6.3 filter与query性能

filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据

query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果

4.7.1 match all 搜索

 

4.7.2 match 搜索

 

4.7.3 multi match(多字段匹配)搜索

 

4.7.4 range query(范围匹配)搜索

 

4.7.5 term query(项匹配)搜索

 

4.7.6 terms query(多值匹配)搜索

 

4.7.7 mach query 组合搜索

 

bool must,must_not,should,filter

每个子查询都会计算一个document针对它的相关度分数,然后bool综合所有分数,合并为一个分数,当然filter是不会计算分数的。

 

filter 是不排序的

定制化排序

 
 

如果对一个string field进行排序,结果往往不准确,因为分词后是多个单词,再排序就不是我们想要的结果了 通常解决方案是,将一个string field建立两次索引,一个分词,用来进行搜索;一个不分词,用来进行排序

PUT /website  

 

初始化数据

 

字符串排序

本文地址:http://ww.kub2b.com/quote/11251.html     企库往 http://ww.kub2b.com/ ,  查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


0相关评论
相关最新动态
推荐最新动态
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号