一、基于scroll技術(shù)滾動搜索大量數(shù)據(jù)
如果一次性要查出來比如10萬條數(shù)據(jù),那么性能會很差,此時一般會采取用scoll滾動查詢, 一批一批的查 直 到 所 有 查 詢 完 為 止 .
- scroll搜索會在笫一次搜索的時候,保存一個當時的視圖快照,之后只會基于該舊的視圖快照提供數(shù)據(jù)捜索,如果這個期間數(shù)據(jù)變更,是不會讓用戶看到的
- 采用基于_doc(不使用_score)進行排序的方式,性能較高
- 每次發(fā)送scroll請求,我們還需要指定一個scoll參數(shù),指定一個時間窗口, 每次搜索請求只要在這個時間窗口內(nèi)能完成就可以了。
//
#查詢第一頁數(shù)據(jù),產(chǎn)生快照
GET /test1/_search?scroll=1m #時間窗口:在1分鐘完成
{
"size":2,
"query":{
"match_all": {}
},
"sort": ["_doc"]
}
#結(jié)果
{
"_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAACDBMWU2dnYWl6VDdSTk9uYU1ESFhJZV9HUQ==",
"took" : 1,
"timed_out" : false,
....
}
#按照上一次產(chǎn)生的結(jié)果的id來繼續(xù)查詢,查詢條件從快照中帶進來,所以不用再寫了
#每次查詢都會產(chǎn)生一個新的_scroll_id,每次查詢都會基于上次的_scroll_id
GET /_search/scroll
{
"scroll":"1m", #1分鐘
"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAACDBMWU2dnYWl6VDdSTk9uYU1ESFhJZV9HUQ=="
}
二、dynamic mapping策略
dynamic:
- true : 遇到陌生字段就 dynamic mapping
- false: 遇到陌生字段就忽略
- strict : 遇到陌生字段就報錯。所見即所得
DELETE /test1
#設(shè)置mapping
PUT /test1
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 0
},
"mappings": {
"dynamic":"strict", #所定義即所得,不可動態(tài)擴展字段
"properties":{
"name":{"type":"text"},
"address":{"type":"object","dynamic":true}
}
}
}
PUT /test1
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 0
},
"mappings": {
"dynamic":"strict", #所定義即所得,不可動態(tài)擴展字段
"date_detection": false, #默認情況下日期格式的數(shù)據(jù)會自動被存成日期類型
"properties":{
"name":{"type":"text"},
"address":{
"type":"object",
"dynamic":true #是動態(tài)映射
}
}
}
}
//
#設(shè)置數(shù)據(jù)
PUT /test1/_doc/1
{
"name":"address",
”age“:10, #添加一個mapping中沒有定義的字段會報錯,dynamic:strict
"address":{
"jie":"dajie",
"hello":"world",
"dao":"dadao" #此處隨意添加字段,因為是dynamic:true
}
}
GET /t
est1/_search
DELETE /test2
PUT /test2
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 0
},
"mappings": {
"dynamic_templates" : [
{
"en":{
"match":"*_en",
"match_mapping_type":"string",
"mapping":{
"type":"text",
"analyzer":"english"
}
}
}
]
}
}
#使用了模板,使用英文分詞器
PUT /test2/_doc/1
{
"test_en":"helo world,this is my dog"
}
#未使用模板(字段非_en結(jié)尾),使用默認的standard分詞器
PUT /test2/_doc/2
{
"test":"helo world,this is my cat"
}
//
GET /test2/_mapping
#英文分詞器中不識別is of 之類的詞,視為結(jié)束詞
#搜索不到結(jié)果,證明根據(jù)字段名自動匹配到了動態(tài)模板
GET /test2/_search
{
"query":{
"match": {
"test_en": "is" #英文分詞器查不到is,但能查到dog
}
}
}
#中國文分詞器中識別is
GET /test2/_search
{
"query":{
"match": {
"test": "is" #中文分詞器能查到is
}
}
}
三、重建索引
?? 一個field的設(shè)置是不能修改的,如果要修改一個field,那么應該重新按照新的mapping建立一個index,然后將數(shù)據(jù)批量查詢出來。重新用bulk api寫入到 index 中。
?? 批量查詢的時候,建議采用scroll api,并且采用多線程并發(fā)的方式來reindex數(shù)據(jù),每次scroll就查詢指定曰期的一段數(shù)據(jù),交給一個線程即可。
PUT /index1/_doc/4
{"content":"1990-12-12"}
GET /index1/_search
GET /index1/_mapping
#修改content的類型為string類型報錯,不允許修改
PUT /index1/_doc/4
{"content":"I am happy"}
#修改content類型為string,報錯,已經(jīng)是date了,不允許你修改
PUT /index1
{
"mappings": {
"properties": {
"content":{
"type":"text"
}
}
}
}
創(chuàng)建一個新的索引,把index索引中的數(shù)據(jù)查詢出來導入到新的索引中。但是應用程序使用的是之前的索引,為了不用重啟應用程序,給index這個索引起個別名。
//
#為原索引創(chuàng)建別名
PUT /index1/_alias/index2
#查看content類型:date
GET /index2/_mapping
#創(chuàng)建新的索引,把content的類型改為字符串
PUT /newindex
{
"mappings": {
"properties": {
"content":{
"type":"text"
}
}
}
}
#使用scroll批量查詢數(shù)據(jù),
GET /index1/_search?scroll=1m
{
"size":2,
"query":{
"match_all": {}
},
"sort": ["_doc"]
}
#再使用bulk批量添加數(shù)據(jù)
POST /_bulk
{"index":{"_index":"newindex","_id":1}}
{"content":"hello world"}
#把新的索引和別名進行關(guān)聯(lián),斷掉舊索引和別名間的關(guān)聯(lián)
POST /_aliases
{
"actions": [
{
"add": {
"index": "newindex",
"alias": "index2"
}
},
{
"remove": {
"index": "index1",
"alias": "index2"
}
}
]
}
#查看content類型:text
GET /index2/_mapping
1. 倒排索引包括
文檔的列表、文檔數(shù)量、詞條在每個文檔中出現(xiàn)的次數(shù)、出現(xiàn)的位置、每個穩(wěn)定的長度、所有文檔的平均長度
2. 索引不變的原因
- 不需要鎖,提升了并發(fā)性能
- 可以一直保存在緩存中(filter)
- 節(jié)省CPU和IO開銷