multi-index和multi-type搜索模式
就是一次性搜索多个index和type下的数据
示例
搜索所有index,所有type下的所有数据
1
GET /_search
指定一个index,搜索其下所有的type的数据
1
GET /index/_search
查询某个index下指定的type的数据
1
GET /index/type/_search
同时搜索多个index下的所有数据
1
GET /index1,index2,index3,.../_search
按照通配符去匹配多个index
1
2GET /*1,*2/_search
# 查询以 1 和 2 结尾的index搜索一个index下指定的多个type的数据
1
GET /index/type1,type2/_search
搜索多个index下的多个type的数据
1
GET /index1,index2/type1,type2/_search
搜索所有index下的指定type的数据
1
GET /_all/type1,type2/_search
搜索原理
客户端发送一个请求,会把请求打到所有的primary shard上去执行,因为每个shard都包含部分数据,所以每个shard上都可能包含搜索请求的结果
但是如果primary shard有replica shard,那么请求也可以打到replica shard上面
分页搜索
查询时传入参数 size 和 from 即可
示例
比如我们要查询movies/movie下的数据一共是6条,分三页查询1
2
3
4
5
6
7
8# 查询第一页
GET /movies/movie/_search?size=2&from=0
# 查询第二页
GET /movies/movie/_search?size=2&from=2
# 查询第三页
GET /movies/movie/_search?size=2&from=4
from 是从0开始的
deep paging问题
什么是deep paging问题? 为什么会产生这个问题? 他的底层原理是什么?
场景,比如我们现在有4个shard 一共有60000条数据,在其中3个shard中,每个有20000条数据,这个时候要进行搜索第1000页的数据,每页显示10条,实际上这里拿到的是第10001~10010条数据
假设这个请求先打到一个不包含这些数据的节点上去,那么这个节点就是一个协调节点(coordinate node),然后这个协调节点会将请求转发到包含数据的节点上去,如图:
查询60000条数据中的第1000页,实际上每个shard都要将内部的20000条数据中的1000页,也就是10001~10010条的数据拿出来, 这时候实际上不是只返回这10条数据 是返回第一条到10010条数据, 3个shard都返回10010条数据给coordinate node,coordinate node 总共会受到30030条数据,然后进行排序,在这30030条数据中取到第10页,也就是这些数据中的第10001~10010条数据返回.
总的来说就是先要把所有shard上的数据集中起来排序后再去分页.
搜索过深的时候,就要在coordinate node上保存大量的数据,还要进行排序,排序之后,再取出对应的那一页,所以这个过程,既耗费网络带宽,耗费内存,还耗费CPU,影响性能,我们应该尽量避免出现这种deep paging的操作
query string
其实就是在http请求中,把一些搜索的参数做为query string附加到url上面.
示例
查询 /movies/movie 下title包含kill这个词的数据1
GET /movies/movie/_search?q=title:kill
查询 /movies/movie 下title必须包含kill这个词的数据1
GET /movies/movie/_search?q=+title:kill
查询/movies/movie 下title不包含kill这个词的数据1
GET /movies/movie/_search?q=-title:kill
其实第一个和第二个的作用是差不多的,主要是 “+” 和 “-“ 的区别 一个是必须包含,一个是不包含
_all metadata 原理和作用
查询所有filed下包含kill的数据1
GET /movies/movie/_search?q=kill
上面这个查询中并没有指定具体是哪个field包含kill这个词,是直接搜索的所有field的.
当我们添加一个document的时候,它里面包含了多个field,此时es会自动将多个field的值,用字符串的方式串联起来,变成一个长字符串,作为_all 的值,同时对 _all进行分词建立索引.
当我们搜索没有指定具体哪一个field的时候,就默认对_all 进行搜索,其实它里面就包含了所有field的值
举例说明
我们新添加一个document,内容是1
2
3
4
5
6{
"name":"jack",
"age":26,
"email" : "jack@sina.com",
"address":"hangzhou"
}
“jack 26 jack@sina.com hangzhou”,就作为这一条document的_all元数据的值,同时进行分词后建立对应的倒排索引