ElasticSearch

Elasticsearch第15节 分页、copy_to、so

2019-06-18  本文已影响0人  小超_8b2f

一、 多索引查询

GET /lib1/_search
GET /lib*/_search
GET /lib1,lib2/_search
GET /lib1,lib2/_search
GET /_all/_search
GET _search

二、 分页查询中的deep paging(深度分页)问题

GET /myindex/_search
{
  "from":0,
  "size":3,
  "version":true,   
  "query":{
    "match":{
      "intrest":"basketball running"
    } 
  }
}
GET /_search?from=0&size=3

deep paging : 查询的很深,比如一个索引有三个primary shard,分别存储了6000条数据,我们要得到笫100页的数据(每页10条),类似这种情况就叫deep paging

1. 如何得到笫100页的10条数据?

1.1 深度分页的错误做法

在每个shard中搜索990到999这10条数据,然后用这30条数据排序,排序之后取10条数据就是要搜索的数据,这种做法是❌的,因为3个shard中的数据的
_score分数不一祥,可能某一个shard中第一条数据的_score分数比另一个shard中笫1000条都要高,所以在每个shard中搜索990到999这10条数据然后排 序的倣法是不正确的。

1.2 深度分页的正确做法

是每个shard把0到999条数据全部搜索出来(按排序顺序),然后全部返回给coordinate node•甶coordinate按_score分数排序后,出第 100页的10条数据,然后返回绐客户端,

1.3 deep paging性能问题
  1. 耗费网络芾宽,因为搜索过深的话,各shard要把数据传送绐coordinate node,这个过程是有大量数据传递的,消耗网络。
  2. 消耗内存,各shard要把数据恃送给coordinate node,这个传递回来的数振,是被coordinate nodW存在内存中的,这样今大量消耗内存.
  3. 消耗cpu coordinate node要把传回来的数据逬行排序,这个排序过程很消耗cpu.
    鉴于deep paging的性能间题,所以应尽量减少使用

三、query String 查询以及copy_to


get /lib1/_search?q=name:xiaochao
get /lib1/_search?q=+name:xiaochao
get /lib1/_search?q=-name:xiaochao
copy_to字段是把其它字段中的值,以空格为分隔符组成一个大字符串,然后被分析和索引,但是不存储,不能显示,只能用来做查询参数。字段类型必须为text

//
DELETE /testindex
#copy_to mapping 提高搜索效率
PUT /testindex
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "age" : {"type" : "long"},
      "birthday" : {"type" : "date"},
      "name" : {"type" : "text","copy_to": "fullContent"},#自定义copy_to字段名
      "content":{"type":"text","copy_to": "fullContent"},#自定义copy_to字段名
      "price":{"type": "double"},
      "number":{"type": "integer"}
    }
  }
}
#数据1
PUT /testindex/_doc/xiaochao
{
  "name":"xiaochao",
  "age":22,
  "birthday":"1991-02-23",
  "content":"good boy",
  "price":100,
  "number":1
}
#数据2
PUT /testindex/_doc/xiaoyi
{
  "name":"xiaoyi",
  "age":22,
  "birthday":"1992-02-23",
  "content":"good girl",
  "price":100,
  "number":1
}
#数据3
PUT /testindex/_doc/xiaofei
{
  "name":"xiaofei",
  "age":22,
  "birthday":"1997-02-23",
  "content":"little girl",
  "price":100,
  "number":1
}
#通过copy_to字段索引,避免全字段检索
GET /testindex/_search?q=fullContent:xiaofei

四、字符型排序


ES对字符串分词了,所以对字符串类型排序不准确,会报错。解决办法:
对字段索引2次,一次索引分词,用于搜索;一次索引不分词,用于排序。

DELETE test1
//
PUT /test1
{
  "mappings": {
    "properties": {
      "age" : {"type" : "long"},
      "birthday" : {"type" : "date","index": false},
      "name" : {
          "type" : "text",
          "fields" : {
            "raw" : {
              "type" : "keyword"    #fields.raw.type=keyword是必须的
            }
          },
          "fielddata":true      #这个必须的
        }
    }
  }
}
#文档1
PUT /test1/_doc/1
{
  "age":10,
  "birthday":"2019-09-23",
  "name":"xiaochao"
}
#文档2
PUT /test1/_doc/2
{
  "age":20,
  "birthday":"2019-02-23",
  "name":"xiaoyi"
}
#文档3
PUT /test1/_doc/3
{
  "age":30,
  "birthday":"2019-07-23",
  "name":"xiaofei"
}
#text查询排序
GET /test1/_search
{
  "query":{
    "match_all": {}
  },
  "sort": [
    {
      "name.raw": {    #.raw是根据整个文本排序,而不是被分的词
        "order": "asc"
      }
    }
  ]
}

五、如何计算相关度分数


使用的是TF/IDF算法(Term Frequency&lnverse Document Frequency)

  1. Term Frequency(词条频率) 我们查询的文本中的词条在 document本 中出现了多少次,出现次数越多,相关度越高
    搜索内容:hello world
#
Hello, I love china.
Hello world,how are you!

2.lnverse Document Frequency(倒排索引频率): 我们查询的文本中的词条在 索引的所有文档中 出现了多少次,出现的次数越多,相关度越低
搜索内容:hello world

//hello在索引的  所有文档中   出现了500次,world出现了 100次 
//所有
hello, what are you doing?
I like the world.
  1. Field-length(字段长度归约)norm : field越长相关度越低
    搜索内容:hello world
//hello 所在文本短,得分高
{'title':"hello,what's your name?',',content':{'owieurowieuolsdjflk'}}
#world所在文本长,得分低
{'title':'hi,good morning','contenf:{'lkjkljkj................world'}}

查看分数是如何计算的:

GET /myindex/_search?explain=true
GET /myindex/_doc/_explain
{
    "query":{
    "match":{
      "intrest":"qwer"
    } 
  }
}

#没有article10的文档
GET /myindex/_doc/article10/_explain
{
    "query":{
    "match":{
      "intrest":"basketball running"
    } 
  }
}
--------------------------------
# Deprecation: [types removal] Specifying a type in explain requests is deprecated.
{
  "_index" : "myindex",
  "_type" : "_doc",
  "_id" : "article10",
  "matched" : false
}

六、 Doc Values 解析 (正排索引)

DocValues其实是Lucene在构建倒排索引时,会额外建立一个有序的正排索引(基于 document => field value的映射列表)
{'birthday':'1985-11-11','age':23}
{birthday':'1989-11-17','age':29}

document age birthday
doc1 23 1985-11-11
doc2 29 1989-11-17

存储在磁盘上,节省内存
对排序、分组和一些聚合操作能够大大提升性能
注意:默认对不分词的字段是开启的,对分词字段无效(需要把fielddata置为true)

doc_values:false 关闭正排索引

//
DELETE test1
#创建mapping
PUT /test1
{
  "mappings": {
    "properties": {
      "age" : {"type" : "long","doc_values":false}, #doc_values 关闭正排索引
      "birthday" : {"type" : "date","index": false},
      "name" : {"type" : "text"}
    }
  }
}
#数据1
PUT /test1/_doc/1
{
  "age":10,
  "birthday":"2019-09-23",
  "name":"xiaochao"
}
#数据2
PUT /test1/_doc/2
{
  "age":20,
  "birthday":"2019-02-23",
  "name":"xiaoyi"
}
#数据3
PUT /test1/_doc/3
{
  "age":30,
  "birthday":"2019-07-23",
  "name":"xiaofei"
}
#查询结果报错
GET /test1/_search
{
  "query":{
    "match_all": {}
  },
  "sort": [
    {
      "age": {
        "order": "asc"
      }
    }
  ]
}
上一篇下一篇

猜你喜欢

热点阅读