資料型別
keyword和text有什麼區別?
keyword用於索引結構化內容的欄位,例如電子郵件地址,主機名,狀態碼,郵政編碼或標籤。
通常用於過濾(找到我的所有部落格文章,其中 status為published),排序,和聚合。keyword型別的欄位只能按其準確值進行搜尋。text是用於全文檢索的資料型別,儲存時會通過分詞器對資料進行分詞儲存,搜尋時會對分詞後的多個短語進行搜尋。text型別不適用用於排序和聚合。
日期型別
Elasticsearch提供了date型別來處理日期,但是由於JSON是沒有日期型別的,所以在內部日期被轉換為UTC並且儲存為時間戳(帶毫秒)。
插入日期時如果插入的為常規日期格式(yyyy-MM-dd
或者yyyy-MM-dd'T'HH:mm:ss.SSSZ
),es會自動識別日期格式,將欄位型別設定為Date
。如果mapping中欄位型別已經確定為Date
,此時插入格式化日期字串或者時間戳(字串和Numeric
型別)時都會被Es作為日期型別儲存,只不過在資料顯示上和儲存時的格式一致(存時間戳返回就是時間戳,字串返回就是字串,但是推薦存標準化的UTC時間或時間戳,避免型別不一致)。
時區問題
A:Elasticsearch預設為UTC時間,即零時區,查詢時若不指定時區,則預設以0時區查詢,和我們所在的東八區差8小時。yyyy-MM-dd'T'HH:mm:ss.SSSZ
,這裡的Z
就代表UTC時區。
Es在進行日期查詢/聚合時可以指定時區:
//日期範圍查詢
POST datatypetest/_search
{
"query": {
"range": {
"date3": {
"gte": "2018-07-05",
"lte": "now",
"time_zone": "Asia/Shanghai"//這就是東八區(北京時間/中國標準時間)
}
}
}
}
//日期聚合
GET my_index/_search?size=0
{
"aggs": {
"by_day": {
"date_histogram": {
"field": "date",
"interval": "day",
"time_zone": "Asia/Shanghai"
}
}
}
}
//Java獲取系統時區id
TimeZone.getDefault().getID()
//Es Java Api日期範圍查詢
QueryBuilders
.rangeQuery("your date field")
.gte("your date from")
.lte("your date to")
.timeZone(TimeZone.getDefault().getID());//此處只能設定時區id
//Es Java Api日期聚合查詢
AggregationBuilders
.dateHistogram("your alias")
.timeZone(DateTimeZone.getDefault());//獲取系統預設時區,此處timeZone物件是joda包中的DateTimeZone
在使用Kibana時,Kibana會預設獲取瀏覽器時區,在顯示資料時根據時區做日期的格式化。但使用DevTools寫DSL或者直接請求Es時預設返回的都是UTC時間,會發現時間少了8小時。
使用日期型別時推薦不修改日期格式時區,所有資料都用UTC時區,這樣時間統一才不容易出問題。
object和nested型別的區別,各自的應用場景是什麼
object為es的預設物件型別,巢狀的json物件存入es就會被預設設定為object型別。es內部會將巢狀的json物件扁平化轉換儲存。
例如,一個普通的json
{
"region": "US",
"manager": {
"age": 30,
"name": {
"first": "John",
"last": "Smith"
}
}
}
在es內部會被轉換為扁平化的基礎json資料
{
"region": "US",
"manager.age": 30,
"manager.name.first": "John",
"manager.name.last": "Smith"
}
nested用於JSON物件的陣列,它允許物件陣列以可彼此獨立查詢的方式進行索引。由於lucene沒有內部物件的概念,因此es需要把資料轉換為簡單的扁平化結構。
一個物件陣列巢狀:
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
在es內部會被轉換為:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
user.first和user.last欄位被轉換為多值欄位,資料之間的關聯性就會丟失,導致查詢結果有誤。
此時用nested型別就可以解決此問題。
查詢
term和match匹配有什麼區別?
term為精確匹配,查詢時不對關鍵詞進行分詞。而match用於全文檢索,首先會對檢索關鍵詞進行分詞,然後進行全文搜尋。
must,filter,post_filter有什麼區別?
must為查詢上下文(query context),查詢時會計算分值(文件相關性)。filter為過濾上下文,查詢時不計算分值。而post_filter為後置過濾器,會對聚合的結果也進行過濾。執行順序為:filter -> aggregations - post_filter。
query context & filter context區別?
must/should為查詢上下文。filter或must_not在引數 bool的查詢中/filter在constant_score的查詢/filter aggretion這些場景中為過濾上下文。
查詢上下文會計算返回文件的分值,而過濾上下文不計算分值,語義只是此文件是否匹配,而不計算相關度。在過濾上下文時,es會自動對過濾器進行快取從而提高查詢效能。