zoukankan      html  css  js  c++  java
  • Elasticsearch 搜索引擎

    1. 搜索结果中的一些词的含义

    took:整个搜索请求花费了多少毫秒;

    hits.total:本次搜索,返回了几条结果;

    hits.max_score:本次搜索的所有结果中,最大的相关度分数是多少,每一条document对于search的相关度,越相关,_score分数越大,排位越靠前;

    hits.hits:默认查询前10条数据,完整数据,_score降序排序;

    shards:shards fail的条件(primary和replica全部挂掉),不影响其他shard。默认情况下来说,一个搜索请求,会打到一个index的所有primary shard上去,每个primary shard都可能会有一个或多个replic shard,所以请求也可以到primary shard的其中一个replica shard上去;

    timeout:默认无timeout,latency平衡completeness,手动指定timeout,timeout查询执行机制;

    GET /_search?timeout=10m 

    timeout查询执行机制指每个shard在timeout时间内,将搜索的部分数据(也可以是全部数据)直接返回给client程序,而不用等到所有的查询结果都查询出来再返回;

    2. multi-index和multi-type搜索模式

    /_search:所有索引,所有type下的所有数据都搜索出来
    /*1,*2/_search:按照通配符去匹配多个索引
    /index1,index2/type1,type2/_search:搜索多个index下的多个type的数据
    /_all/type1,type2/_search:_all,可以代表搜索所有index下的指定type的数据

    3.搜索原理初步

    client会把一个请求打到所有primary shard上去执行,因为每个shard都包含了部分数据,所以每个shard都可能包含了搜索请求的结果,因为每个primary shard 都包含replica shard,所以请求也会打到replica shard上。

    4.分布搜索

    GET /_search?size=10&from=20

    5.deep paging 问题 

    简单说,就是搜溹的特别深;

    带来的问题:coordinate node 上需要保存大量的数据,还需进行大量数据的排序,排序之后再取出对应的那一页,这个过程耗费网络带宽,耗费内存和CPU;

    6.query string 基础语法

    GET /test_index/test_type/_search?q=test_field:test
    GET /test_index/test_type/_search?q=+test_field:test  必须包含和上面一样
    GET /test_index/test_type/_search?q=-test_field:test   必须不包含

    _all metadata的原理和作用:

    我们并不是对document中的每一个field进行一个一个的搜索,_all元数据在建立索引的时候,我们插入一个document,里面包含了多个field,此时es会将里面多个field的值用字符串拼接起来,同时建立索引,我们在不对特定的field的进行搜索的时候,就会从_all field 中进行搜溹;

    7.mapping

    定义:自动或手动为index中的type建立的一种数据结构和相关配置,简称为mapping;mapping就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为;

    mapping建立过程:

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

    dynamic mapping,自动为我们建立index,创建type,以及type对应的mapping,mapping中包含了每个field对应的数据类型,以及如何分词等设置;

    true or false --> boolean
    123 --> long
    123.45 --> double
    2017-01-01 --> date
    "hello world" --> string/text

    mapping的查看:GET /index/_mapping/type

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

    PUT /website
    {
      "mappings": {
        "article": {
          "properties": {
            "author_id": {
              "type": "long"
            },
            "title": {
              "type": "text",
              "analyzer": "english"
            },
            "content": {
              "type": "text"
            },
            "post_date": {
              "type": "date"
            },
            "publisher_id": {
              "type": "text",
              "index": "not_analyzed"
            }
          }
        }
      }
    }

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

    不同类型的field,可能有的就是full text,有的就是exact value;

    8.倒排索引

    在建立倒排索引前,会先执行一个操作,对拆分出来的单词进行处理(normalization),来提升搜索时能搜到的概率;

    9. 分词器

    内置的分词器:standard analyzer,simple analyzer,whitespace analyzer,language analyzer

    分词器查看 GET /_analyze

    10. http协议中get是否可以带上request body

    HTTP协议,一般不允许get请求带上request body,但是因为get更加适合描述查询数据的操作,因此还是这么用了;

    GET /_search?from=0&size=10

    POST /_search
    {
    "from":0,
    "size":10
    }

    11. Query DSL的基本语法

    {
         QUERY_NAME: {
                  ARGUMENT: VALUE,
                  ARGUMENT: VALUE,...
            }
    }

    {
            QUERY_NAME: {
               FIELD_NAME: {
                 ARGUMENT: VALUE,
                 ARGUMENT: VALUE,...
                }
           }
    }

    GET /test_index/test_type/_search 
    {
      "query": {
        "match": {
          "test_field": "test"
        }
      }
    }
    

    组合搜索条件:

    搜索需求:title必须包含elasticsearch,content可以包含elasticsearch也可以不包含,author_id必须不为111
    GET /website/article/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "title": "elasticsearch"
              }
            }
          ],
          "should": [
            {
              "match": {
                "content": "elasticsearch"
              }
            }
          ],
          "must_not": [
            {
              "match": {
                "author_id": 111
              }
            }
          ]
        }
      }
    }

    12. filter实例

    filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响;
    query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序;

    一般来说,如果你是在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter
    除非是你的这些搜索条件,你希望越符合这些搜索条件的document越排在前面返回,那么这些搜索条件要放在query中;如果你不希望一些搜索条件来影响你的document排序,那么就放在filter中即可;

    filter与query性能对比:
    filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据;
    query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果

    GET /company/employee/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "join_date": "2016-01-01"
              }
            }
          ],
          "filter": {
            "range": {
              "age": {
                "gte": 30
              }
            }
          }
        }
      }
    }

    13. query搜索语法

    1)、match all
    
    GET /_search
    {
        "query": {
            "match_all": {}
        }
    }
    
    2)、match
    
    GET /_search
    {
        "query": { "match": { "title": "my elasticsearch article" }}
    }
    
    3)、multi match
    
    GET /test_index/test_type/_search
    {
      "query": {
        "multi_match": {
          "query": "test",
          "fields": ["test_field", "test_field1"]
        }
      }
    }
    
    4)、range query
    
    GET /company/employee/_search 
    {
      "query": {
        "range": {
          "age": {
            "gte": 30
          }
        }
      }
    }
    
    5)、term query
    
    GET /test_index/test_type/_search 
    {
      "query": {
        "term": {
          "test_field": "test hello"
        }
      }
    }
    
    6)、terms query
    
    GET /_search
    {
        "query": { "terms": { "tag": [ "search", "full_text", "nosql" ] }}
    }

    14. 快速验证错误原因

    GET /test_index/test_type/_validate/query?explain

    {
    "query": {
    "math": {
    "test_field": "test"
    }
    }
    }

    15.排序规则

    1)默认情况下是有按照score进行降序排序的,对比没有score时(filter),可以使用constant_score

    GET /_search
    {
        "query" : {
            "constant_score" : {
                "filter" : {
                    "term" : {
                        "author_id" : 1
                    }
                }
            }
        }
    }

    2) 定制排序规则:

    GET /company/employee/_search 
    {
      "query": {
        "constant_score": {
          "filter": {
            "range": {
              "age": {
                "gte": 30
              }
            }
          }
        }
      },
      "sort": [
        {
          "join_date": {
            "order": "asc"
          }
        }
      ]
    }

    16. TF-IDF算法

    Term frequency(TF):搜索文本中的各个词条在field文本中出现了多少次,出现次数越多,就越相关;

    Inverse document frequency(IDF):搜索文本中的各个词条在整个索引的所有文档中出现了多少次,出现的次数越多,就越不相关;

    Field-length norm:field长度,field越长,相关度越弱;

    1)_score是如何被计算出来的?

    GET /test_index/test_type/_search?explain
    {
      "query": {
        "match": {
          "test_field": "test hello"
        }
      }
    }

    2)分析一个document是如何被匹配上的

    GET /test_index/test_type/6/_explain
    {
      "query": {
        "match": {
          "test_field": "test hello"
        }
      }
    }

    17. doc values

    搜索的时候,要依靠倒排索引;排序的时候,需要依靠正排索引(doc values)

    doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高;如果内存不足够,os会将其写入磁盘上;

    18. query phase

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

    replica shard如何提升搜索吞吐量?

    一次请求要打到所有shard的一个replica/primary上去,如果每个shard都有多个replica,那么同时并发过来的搜索请求可以同时打到其他的replica上去;

    19. fetch phase

    1)在query phase结束时,coordinate node构建完全局priority queue之后,就发送mget请求去所有shard上获取对应的document;
    2)各个shard将document返回给coordinate node;
    3)coordinate node将合并后的document结果返回给client客户端;

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

    20. 参数preference,search_type

    1)决定了哪些shard会被用来执行搜索操作

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

    2)bouncing results问题

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

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

    3)search_type

    default:query_then_fetch
    dfs_query_then_fetch,可以提升revelance sort精准度

    21. scoll技术

    scoll滚动查询,一批一批的查,直到所有数据都查询完处理完;

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

    GET /test_index/test_type/_search?scroll=1m
    {
    "query": {
    "match_all": {}
    },
    "sort": [ "_doc" ],
    "size": 3
    }

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

    GET /_search/scroll
    {
    "scroll": "1m", 
    "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAACxeFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYBY0b25zVFlWWlRqR3ZJajlfc3BXejJ3AAAAAAAALF8WNG9uc1RZVlpUakd2SWo5X3NwV3oydwAAAAAAACxhFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYhY0b25zVFlWWlRqR3ZJajlfc3BXejJ3"
    }
  • 相关阅读:
    JVM类加载的过程
    接口文档设计
    代码规范及CodeReview要点
    Linux权限
    Linux文件
    UltraEdit编辑器基础技巧
    Android环境配置
    JDK 环境配置
    xml没有提示解决办法<eclipse>
    mysql事务实例
  • 原文地址:https://www.cnblogs.com/ntbww93/p/9815740.html
Copyright © 2011-2022 走看看