2、es---搜索引擎

一、get /_search 结果详情

1、结果

GET /_search

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 6,
    "successful": 6,
    "failed": 0
  },
  "hits": {
    "total": 10,
    "max_score": 1,
    "hits": [
      {
        "_index": ".kibana",
        "_type": "config",
        "_id": "5.2.0",
        "_score": 1,
        "_source": {
          "buildNum": 14695
        }
      }
    ]
  }
}

2、解析

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上去。

3、timeout机制

a、设置timeout:GET /_search?timeout=10m
b、timeout机制:指定每个shard,就只能在timeout时间范围内,将搜索到的部分数据(也可能搜索到了全部数据),直接返给client程序,而不是等到所有数据全部都搜索出来再返回给client

 

二、multi-index和multi-type搜索模式

1、告诉你如何一次性搜索多个index和多个type下的数据

2、事例:

/_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的数据

 

三、es进行分页搜索的语法

1、实例:GET /_search?size=10&from=20

 

四、query string

1、基础语法

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

一个是掌握q=field:search content的语法,还有一个是掌握+和-的含义

2、_all metadata的原理和作用

a、es中的_all元数据,在建立索引的时候,我们插入一条document,它里面包含了多个field,此时,es会自动将多个field的值,全部用字符串的方式串联起来,变成一个长的字符串,作为_all field的值,同时建立索引

b、例:

{
  "name": "jack",
  "age": 26,
  "email": "jack@sina.com",
  "address": "guamgzhou"
}

--------->_all field = jack 26 jack@sina.com guamgzhou
"jack 26 jack@sina.com guangzhou",作为这一条document的_all field的值,同时进行分词后建立对应的倒排索引

 

五:mapping

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

2、查询mapping结构:GET /index/_mapping/type

{
  "website": {
    "mappings": {
      "article": {
        "properties": {
          "author_id": {
            "type": "long"
          },
          "post_date": {
            "type": "date"
          },
        }
      }
    }
  }
}

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

 

六、精准匹配与全文搜索

1、精准匹配:exact value

doc 的field与搜索的关键词完全匹配才能搜索出来

2、全文检索:full text

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

如:

(1)缩写 vs. 全程:cn vs. china
(2)格式转化:like liked likes
(3)大小写:Tom vs tom
(4)同义词:like vs love

 

七、倒排索引原理

1、将内容分词--->初步建立倒排索引--->normalization

2、normalization:对拆分出的各个单词进行相应的处理,以提升后面搜索的时候能够搜索到相关联的文档的概率 如:单复数的转换,同义词的转换,大小写的转换

 

八、分词器

1、什么是分词器?

切分词语,normalization(提升recall召回率)

2、分词步骤

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

3、分词器种类

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

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

 

九、query string

1、查询的内容就是query string

2、默认情况下,es会使用它对应的field建立倒排索引时相同的分词器去对query string进行分词

a、每个field都会建立倒排索引,特殊field:_all

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

date:exact value
_all:full text

3、query string对exact value和full text的区别对待

4、测试分词器

GET /_analyze
{
  "analyzer": "standard",
  "text": "Text to analyze"
}

结果:{tokens:[{token1},{token2}]}--------->每个token就是被拆分的一个词语

十、综上总结

(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 query string,也会进行分词和normalization再去倒排索引中去搜索
(6)可以用es的dynamic mapping,让其自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,自己对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等


mapping,就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为

 

十一、mapping对应的数据类型

1、核心的数据类型
string/text
byte,short,integer,long
float,double
boolean
date

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

3、查看mapping
GET /index/_mapping/type

 

十二、string类型数据是否分词

1、分词类型

analyzed
not_analyzed------>field type为keyword,keyword不会进行分词
no---->不能搜索

2、建立mapping

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

a、建立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"
        }
      }
    }
  }
}

b、添加field

PUT /website/_mapping/article
{
  "properties" : {
    "new_field" : {
      "type" :    "string",
      "index":    "not_analyzed"
    }
  }
}

3、测试mapping

GET /website/_analyze
{
  "field": "content",
  "text": "my-dogs" 
}

结果:{tokens:[{token1},{token2}]}--------->每个token就是被拆分的一个词语

 

十二、特殊类型的field

1、multivalue field
{ "tags": [ "tag1", "tag2" ]}
建立索引时与string是一样的,数据类型不能混

2、empty field
null,[],[null]

3、object field
PUT /company/employee/1
{
  "address": {
    "country": "china",
    "province": "guangdong",
    "city": "guangzhou"
  },
  "name": "jack",
  "age": 27,
  "join_date": "2017-01-01"
}

 

十三、query DSL

1、语法

bool:多条件查询,里面放must、should、must_not、filter

must:必须匹配
should:可以匹配也可以不匹配
must_not:必须不能匹配

match_all:查询所有doc
match:条件匹配
multi match:匹配多个field
range query:范围查询
term query:不会对查询条件进行拆分(整个内容去匹配)

2、filter性能

filter:不需要计算相关度分数,不需要按照相关度分数进行排序

query:相反,要计算相关度分数,按照分数进行排序

3、验证搜索是否合法

GET /index/type/_validate/query?explain

4、定制排序规则

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

5、如果对一个string field进行排序,结果往往不准确,因为分词后是多个单词,再排序就不是我们想要的结果了

解决:将一个string field建立两次索引,一个分词,用来进行搜索;一个不分词,用来进行排序

例如:

建立mapping:

PUT /website 
{
  "mappings": {
    "article": {
      "properties": {
        "title": {
          "type": "text",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          },
          "fielddata": true
        },
        "content": {
          "type": "text"
        },
        "post_date": {
          "type": "date"
        },
        "author_id": {
          "type": "long"
        }
      }
    }
  }
}

查询:

GET /website/article/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "title.raw": {
        "order": "desc"
      }
    }
  ]
}

 

十四、TF/IDF算法

Elasticsearch使用的是 term frequency/inverse document frequency算法,简称为TF/IDF算法

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

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

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

4、_score是如何被计算出来的: GET /test_index/test_type/_search?explain

5、分析一个document是如何被匹配上的: GET /test_index/test_type/6/_explain

 

十五、正排索引和倒排索引(doc values)

1、搜索的时候,要依靠倒排索引;排序的时候,需要依靠正排索引,所谓的正排索引,其实就是doc values

2、倒排索引

doc1: hello world you and me
doc2: hi, world, how are you

word        doc1        doc2

hello            *
world           *            *
you              *            *
and              *
me               *
hi                              *
how                          *
are                            *

3、正排索引

doc1: { "name": "jack", "age": 27 }
doc2: { "name": "tom", "age": 30 }

document    name        age

 doc1              jack         27
 doc2              tom         30    

 

十六、搜索先关参数

1、preference:决定了哪些shard会被用来执行搜索操作
可用配置:_primary, _primary_first, _local, _only_node:xyz, _prefer_node:xyz, _shards:2,3

2、timeout:主要就是限定在一定时间内,将部分获取到的数据直接返回,避免查询耗时过长

3、routing:document文档路由,_id路由,routing=user_id(默认是doc_id),这样的话可以让同一个user对应的数据到一个shard上去

4、search_type

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

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

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

 

十七、scroll技术

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

2、scoll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的。采用基于_doc进行排序的方式,性能较高

3、每次发送scroll请求,我们还需要指定一个scoll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了

4、例如:

GET /test_index/test_type/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "sort": [ "_doc" ],
  "size": 3------------------------->每次查询出的个数

查询出的结果会有个_scroll_id,下次查询再根据这个_scroll_id进行查询

GET /_search/scroll
{
    "scroll": "1m", 
    "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAACxeFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYBY0b25zVFlWWlRqR3ZJajlfc3BXejJ3AAAAAAAALF8WNG9uc1RZVlpUakd2SWo5X3NwV3oydwAAAAAAACxhFjRvbnNUWVZaVGpHdklqOV9zcFd6MncAAAAAAAAsYhY0b25zVFlWWlRqR3ZJajlfc3BXejJ3"
}
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值