Elasticsearch——search搜索入门

2020-11-15  本文已影响0人  小波同学

Search的运行机制

Search执行的时候分为两个运行步骤:

Query阶段

Fetch阶段

相关性算分问题

相关性算分在shard与shard之间是相互独立的,也就意味着同一个Term的IDF等值在不同shard上是不同的,文档的相关性算分和它所处的shard相关,在文档数量不多时,会导致相关性算分严重不准的情况发生。

解决思路有两个:

排序

es默认会采用相关性算分排序,用户可以通过设定sorting参数来自行设定排序规则

Fielddata VS DocValues

对比 Fielddata DocValues
创建时机 搜索时即时创建 索引时创建,与倒排索引
创建时机一致
创建位置 JVM Heap 磁盘
优点 不会占用额外的磁盘资源 不会占用Heap内存
缺点 文档过多时,即时创建会花费过多时间,
占用过多的Heap内存
减慢索引的速度,占用
额外的磁盘空间

Fielddata

Fielddata默认是关闭的,可以通过如下api开启:

DocValues

DocValues默认是启用的,可以在创建索引的时候关闭,如果后面要开启DocValues,需要做reindex操作。


DocValue_fields

可以通过该字段获取fielddata获取DocValues中储存的内容。


搜索语法入门

query string search

无条件搜索所有

GET /book/_search
{
  "took" : 969,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "Bootstrap开发",
          "description" : "Bootstrap是由Twitter推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个css,不受浏览器限制的精美界面css效果。",
          "studymodel" : "201002",
          "price" : 38.6,
          "timestamp" : "2019-08-25 19:11:35",
          "pic" : "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
          "tags" : [
            "bootstrap",
            "dev"
          ]
        }
      },
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "java编程思想",
          "description" : "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
          "studymodel" : "201001",
          "price" : 68.6,
          "timestamp" : "2019-08-25 19:11:35",
          "pic" : "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
          "tags" : [
            "java",
            "dev"
          ]
        }
      },
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "spring开发基础",
          "description" : "spring 在java领域非常流行,java程序员都在用。",
          "studymodel" : "201001",
          "price" : 88.6,
          "timestamp" : "2019-08-24 19:11:35",
          "pic" : "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
          "tags" : [
            "spring",
            "java"
          ]
        }
      }
    ]
  }
}

解释

传参

与http请求传参类似

GET /book/_search?q=name:java&sort=price:desc
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "name" : "java编程思想",
          "description" : "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
          "studymodel" : "201001",
          "price" : 68.6,
          "timestamp" : "2019-08-25 19:11:35",
          "pic" : "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg",
          "tags" : [
            "java",
            "dev"
          ]
        },
        "sort" : [
          68.6
        ]
      }
    ]
  }
}

timeout机制

GET /index/_search?timeout=10ms

默认情况下,es的timeout机制是关闭的。比如,如果你的搜索特别慢,每个shard都要花好几分钟才能查询出来所有的数据,那么你的搜索请求也会等待好几分钟才会返回。

我们有些应用系统对时间是非常敏感的,比如说电商网站,你不能让用户等10分钟,才能等到一次搜索请求的结果。

timeout机制:指定每个shard只能在timeout时间范围内,将搜索到的部分数据(也可能是全部数据),直接返回给客户端,而不是等到所有的数据全部搜索出来以后再返回。确保一次搜索请求可以在用户指定的timeout时长内完成,为一些时间敏感的搜索应用提供良好的支持。

全局设置:配置文件中设置search.default_search_timeout:100ms。该设置不常用。

multi-index 多索引搜索

multi-index搜索模式

如何一次性搜索多个index和多个type下的数据

/_search:所有索引下的所有数据都搜索出来
/index1/_search:指定一个index,搜索其下所有的数据
/index1,index2/_search:同时搜索两个index下的数据
/index*/_search:按照通配符去匹配多个索引

应用场景:生产环境log索引可以按照日期分开。

log_to_es_20201110
log_to_es_20201111
log_to_es_20201112

分页与遍历

es提供了3种方式来解决分页与遍历的问题:

from/size

最常用的分页方案:

GET /index/_search?size=10
GET /index/_search?size=10&from=0

如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:

GET /book/_search?size=5
​GET /book/_search?size=5&from=5
​GET /book/_search?size=5&from=10

深度分页是一个经典问题:在数据分片存储的情况下,如何获取前1000条数据?

除了会遇到效率上的问题,还有一个无法解决的问题是es目前支持最大的skip值是max_result_window默认为10000,也就是说当from+size > max_result_window时,es将返回错误。

解决方案:
问题描述:比如当客户线上的es数据出现问题,当分页到几百页的时候,es无法返回数据,此时为了恢复正常使用,我们可以采用紧急规避的方式,就是将max_result_window的值调至50000。

curl -XPUT "127.0.0.1:9200/custm/_settings" -d 
'{ 
    "index" : { 
        "max_result_window" : 50000 
    }
}'

对于上面这种解决方案只是暂时解决问题,当es的使用越来越多时,数据量越来越大,深度分页的场景越来越复杂时,可以使用另一种分页方式scroll。

deep paging

什么是deep paging

deep paging问题

scroll

遍历文档集的api,以快照的方式来避免深度分页的问题。

search_after

应用场景:
类型 场景
From/Size 需要实时获取顶部的部分文档,且需要自由翻页
Scroll 需要全部文档,如导出所有数据的功能
Search_after 需要全部文档,不需要自由翻页

query string基础语法

GET /book/_search?q=name:java
GET /book/_search?q=+name:java
GET /book/_search?q=-name:java

_all metadata的原理和作用

GET /book/_search?q=java

直接可以搜索所有的field,任意一个field包含指定的关键字就可以搜索出来。我们在进行中搜索的时候,难道是对document中的每一个field都进行一次搜索吗?不是的。

es中all元数据。建立索引的时候,插入一条document,es会将所有的field值经行全量分词,把这些分词,放到all field中。在搜索的时候,没有指定field,就在_all搜索。

举例

{
    name:jack
    email:123@qq.com
    address:beijing
}

_all : jack,123@qq.com,beijing

参考:
https://blog.csdn.net/fy_java1995/article/details/106674455

https://www.cnblogs.com/qinjf/p/8519444.html

上一篇 下一篇

猜你喜欢

热点阅读