一、 多索引查詢
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條數(shù)據(jù),我們要得到笫100頁的數(shù)據(jù)(每頁10條),類似這種情況就叫deep paging
1. 如何得到笫100頁的10條數(shù)據(jù)?
1.1 深度分頁的錯誤做法
在每個shard中搜索990到999這10條數(shù)據(jù),然后用這30條數(shù)據(jù)排序,排序之后取10條數(shù)據(jù)就是要搜索的數(shù)據(jù),這種做法是?的,因為3個shard中的數(shù)據(jù)的
_score分數(shù)不一祥,可能某一個shard中第一條數(shù)據(jù)的_score分數(shù)比另一個shard中笫1000條都要高,所以在每個shard中搜索990到999這10條數(shù)據(jù)然后排 序的倣法是不正確的。
1.2 深度分頁的正確做法
是每個shard把0到999條數(shù)據(jù)全部搜索出來(按排序順序),然后全部返回給coordinate node?甶coordinate按_score分數(shù)排序后,出第 100頁的10條數(shù)據(jù),然后返回紿客戶端,
1.3 deep paging性能問題
- 耗費網(wǎng)絡(luò)芾寬,因為搜索過深的話,各shard要把數(shù)據(jù)傳送紿coordinate node,這個過程是有大量數(shù)據(jù)傳遞的,消耗網(wǎng)絡(luò)。
- 消耗內(nèi)存,各shard要把數(shù)據(jù)恃送給coordinate node,這個傳遞回來的數(shù)振,是被coordinate nodW存在內(nèi)存中的,這樣今大量消耗內(nèi)存.
-
消耗cpu coordinate node要把傳回來的數(shù)據(jù)逬行排序,這個排序過程很消耗cpu.
鑒于deep paging的性能間題,所以應(yīng)盡量減少使用
三、query String 查詢以及copy_to
get /lib1/_search?q=name:xiaochao
get /lib1/_search?q=+name:xiaochao
get /lib1/_search?q=-name:xiaochao
copy_to字段是把其它字段中的值,以空格為分隔符組成一個大字符串,然后被分析和索引,但是不存儲,不能顯示,只能用來做查詢參數(shù)。字段類型必須為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"}
}
}
}
#數(shù)據(jù)1
PUT /testindex/_doc/xiaochao
{
"name":"xiaochao",
"age":22,
"birthday":"1991-02-23",
"content":"good boy",
"price":100,
"number":1
}
#數(shù)據(jù)2
PUT /testindex/_doc/xiaoyi
{
"name":"xiaoyi",
"age":22,
"birthday":"1992-02-23",
"content":"good girl",
"price":100,
"number":1
}
#數(shù)據(jù)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是根據(jù)整個文本排序,而不是被分的詞
"order": "asc"
}
}
]
}
五、如何計算相關(guān)度分數(shù)
使用的是TF/IDF算法(Term Frequency&lnverse Document Frequency)
-
Term Frequency(詞條頻率) 我們查詢的文本中的詞條在 document本 中出現(xiàn)了多少次,出現(xiàn)次數(shù)越多,相關(guān)度越高
搜索內(nèi)容:hello world
#
Hello, I love china.
Hello world,how are you!
2.lnverse Document Frequency(倒排索引頻率): 我們查詢的文本中的詞條在 索引的所有文檔中 出現(xiàn)了多少次,出現(xiàn)的次數(shù)越多,相關(guān)度越低
搜索內(nèi)容:hello world
//hello在索引的 所有文檔中 出現(xiàn)了500次,world出現(xiàn)了 100次
//所有
hello, what are you doing?
I like the world.
-
Field-length(字段長度歸約)norm : field越長相關(guān)度越低
搜索內(nèi)容:hello world
//hello 所在文本短,得分高
{'title':"hello,what's your name?',',content':{'owieurowieuolsdjflk'}}
#world所在文本長,得分低
{'title':'hi,good morning','contenf:{'lkjkljkj................world'}}
查看分數(shù)是如何計算的:
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在構(gòu)建倒排索引時,會額外建立一個有序的正排索引(基于 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 |
存儲在磁盤上,節(jié)省內(nèi)存
對排序、分組和一些聚合操作能夠大大提升性能
注意:默認對不分詞的字段是開啟的,對分詞字段無效(需要把fielddata置為true)
doc_values:false 關(guān)閉正排索引
//
DELETE test1
#創(chuàng)建mapping
PUT /test1
{
"mappings": {
"properties": {
"age" : {"type" : "long","doc_values":false}, #doc_values 關(guān)閉正排索引
"birthday" : {"type" : "date","index": false},
"name" : {"type" : "text"}
}
}
}
#數(shù)據(jù)1
PUT /test1/_doc/1
{
"age":10,
"birthday":"2019-09-23",
"name":"xiaochao"
}
#數(shù)據(jù)2
PUT /test1/_doc/2
{
"age":20,
"birthday":"2019-02-23",
"name":"xiaoyi"
}
#數(shù)據(jù)3
PUT /test1/_doc/3
{
"age":30,
"birthday":"2019-07-23",
"name":"xiaofei"
}
#查詢結(jié)果報錯
GET /test1/_search
{
"query":{
"match_all": {}
},
"sort": [
{
"age": {
"order": "asc"
}
}
]
}