1. 常见的搜索模式有如下形式:
/_search:所有索引,所有type下的所有数据都搜索出来
/index1/_search:指定一个index,搜索其下所有type的数据
/index1,index2/_search:同时搜索两个index下的数据
/*1,*2/_search:按照通配符去匹 配多个索引
/index1/type1/_search:搜索一个index下指定的type的数据
/index1/type1,type2/_search:可以搜索一个index下多个type的数据
/index1,index2/type1,type2/_search:搜索多个index下的多个type的数据
/_all/type1,type2/_search:_all,可以代表搜索所有index下的指定type的数据
因为每个shard都只是包含部分数据,所以client搜索请求会发到对应的所有primary shard和replica shard上去。
2. 分页搜索
size(搜索大小),from(起始位置)
GET /_search?size=10
GET /_search?size=10&from=0
GET /_search?size=10&from=20
3. deep paging问题
当要搜索的数据特别多,也就是搜索的特别深。
比如数据量有90000条,3个shard,每个shard上分了30000条,每页10条数据,这个时候搜到1000页的话,客户端实际想要拿到的数据是10001~10010这10条数据。在搜索的时候,对于每个shard,他们要返回的数据并不是10条数据,而是10010条数据,也就是每个shard都要返回10010条数据给coordinate node,那么coordinate node总共接收到30030条数据,然后根据_score相关度排序,最后取到排位最高的10条数据返回给client。
这样就导致,coordinate node上保存大量的数据,还要进行大量数据的排序,排序后在取出对应的那一页,这就会耗费内存,网络带款和CPU,产生性能问题,所以要尽量避免出现这种操作。
4. query string基础语法
GET /test_index/test_type/_search?q=test_field:test //搜索所有含有test的内容
GET /test_index/test_type/_search?q=+test_field:test //必须含有test,作用与第一条是一样的
GET /test_index/test_type/_search?q=-test_field:test //不能含有test
5. _all metadata
直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来。我们在进行中搜索的时候,难道是对document中的每一个field都进行一次搜索吗?不是的
es中的_all元数据,在建立索引的时候,我们插入一条document,它里面包含了多个field,此时,es会自动将多个field的值,全部用字符串的方式串联起来,变成一个长的字符串,作为_all field的值,同时建立索引
后面如果在搜索的时候,没有对某个field指定搜索,就默认搜索_all field,其中是包含了所有field的值的
举个例子
{
"name": "jack",
"age": 26,
"email": "jack@sina.com",
"address": "guamgzhou"
}
"jack 26 jack@sina.com guangzhou",作为这一条document的_all field的值,同时进行分词后建立对应的倒排索引
6. mapping
创建document的时候,默认ES会自动建立mapping,不同的field设置为不同的data type,不同的data type的分词、搜索行为是不一样的,这会影响关键字的搜索结果。一个mapping的形式如下:
GET /website/_mapping/article
{
"website": {
"mappings": {
"article": {
"properties": {
"author_id": {
"type": "long"
},
"content": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"post_date": {
"type": "date"
},
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
mapping也可以手动建立,没有手动建立的话,ES自动建立的mapping称为dynamic mapping。
7. 搜索模式
精确搜索(exact value):
完全按搜索字符串匹配,多了字符或少了字符都不能搜索到。
全文搜索(full text):
以下情况都可以搜索到
(1)缩写 vs. 全程:cn vs. china
(2)格式转化:like liked likes
(3)大小写:Tom vs tom
(4)同义词:like vs love
2017-01-01,2017 01 01,搜索2017,或者01,都可以搜索出来
china,搜索cn,也可以将china搜索出来
likes,搜索like,也可以将likes搜索出来
Tom,搜索tom,也可以将Tom搜索出来
like,搜索love,同义词,也可以将like搜索出来
就不是说单纯的只是匹配完整的一个值,而是可以对值进行拆分词语后(分词)进行匹配,也可以通过缩写、时态、大小写、同义词等进行匹配。
8. mapping搜索案例
插入如下3条数据:
PUT /website/article/1
{
"post_date": "2017-01-01",
"title": "my first article",
"content": "this is my first article in this website",
"author_id": 11400
}
PUT /website/article/2
{
"post_date": "2017-01-02",
"title": "my second article",
"content": "this is my second article in this website",
"author_id": 11400
}
PUT /website/article/3
{
"post_date": "2017-01-03",
"title": "my third article",
"content": "this is my third article in this website",
"author_id": 11400
}
尝试各种搜索
GET /website/article/_search?q=2017 3条结果:这是一个全文搜索,上面3条数据进行分词器处理后,都含有2017,因此都可以被搜索到。
GET /website/article/_search?q=2017-01-01 3条结果:这也是一个全文搜索,上面3条数据进行分词器处理后,都含有2017,并且搜索字符串也要经过分词器处理,含有2017,故3条数据也都可以被搜索到。
GET /website/article/_search?q=post_date:2017-01-01 1条结果:这是一个精确搜索,只有含有2017-01-01的记录才能被搜索到。
GET /website/article/_search?q=post_date:2017 1条结果