2016-01-21 109 views
3

「星期幾」我有一個類中的下列財產:Elasticsearch - 日期時間映射

public DateTime InsertedTimeStamp { get; set; } 

通過以下映射在ES

"insertedTimeStamp ":{ 
    "type":"date", 
    "format":"yyyy-MM-ddTHH:mm:ssZ" 
}, 

我想運行聚合返回按照「星期幾」分組的所有數據,即「星期一」,「星期二」...等

我知道我可以在聚合調用中使用'腳本'來執行此操作,see here,然而,從米如果有大量文件(這裏反對,認爲分析日誌),使用腳本對性能的影響不會有微不足道的影響。

有沒有一種方法可以將屬性與'子屬性'進行映射。即用字符串我可以這樣做:

"somestring":{ 
    "type":"string", 
    "analyzer":"full_word", 
    "fields":{ 
     "partial":{ 
      "search_analyzer":"full_word", 
      "analyzer":"partial_word", 
      "type":"string" 
     }, 
     "partial_back":{ 
      "search_analyzer":"full_word", 
      "analyzer":"partial_word_back", 
      "type":"string" 
     }, 
     "partial_middle":{ 
      "search_analyzer":"full_word", 
      "analyzer":"partial_word_name", 
      "type":"string" 
     } 
    } 
}, 

所有以.net代碼在類中的一個屬性。

我可以做一些類似的事情,分別存儲'完整日期'和'年份','月份'和'日'等(索引時某種'腳本'),或者我需要做更多類中的屬性並分別映射它們?這是Transform做的嗎? (這是現在貶值,因此似乎表明我需要單獨的領域......)

回答

4

絕對有可能在索引時使用pattern_capture token filter來做到這一點。

您首先要爲每個日期部分定義一個分析器+標記過濾器組合,並將其分配給日期字段的子字段。每個令牌過濾器將只捕獲組是感興趣的

{ 
    "settings": { 
    "analysis": { 
     "analyzer": { 
     "year_analyzer": { 
      "type": "custom", 
      "tokenizer": "keyword", 
      "filter": [ 
      "year" 
      ] 
     }, 
     "month_analyzer": { 
      "type": "custom", 
      "tokenizer": "keyword", 
      "filter": [ 
      "month" 
      ] 
     }, 
     "day_analyzer": { 
      "type": "custom", 
      "tokenizer": "keyword", 
      "filter": [ 
      "day" 
      ] 
     }, 
     "hour_analyzer": { 
      "type": "custom", 
      "tokenizer": "keyword", 
      "filter": [ 
      "hour" 
      ] 
     }, 
     "minute_analyzer": { 
      "type": "custom", 
      "tokenizer": "keyword", 
      "filter": [ 
      "minute" 
      ] 
     }, 
     "second_analyzer": { 
      "type": "custom", 
      "tokenizer": "keyword", 
      "filter": [ 
      "second" 
      ] 
     } 
     }, 
     "filter": { 
     "year": { 
      "type": "pattern_capture", 
      "preserve_original": false, 
      "patterns": [ 
      "(\\d{4})-\\d{2}-\\d{2}[tT]\\d{2}:\\d{2}:\\d{2}[zZ]" 
      ] 
     }, 
     "month": { 
      "type": "pattern_capture", 
      "preserve_original": false, 
      "patterns": [ 
      "\\d{4}-(\\d{2})-\\d{2}[tT]\\d{2}:\\d{2}:\\d{2}[zZ]" 
      ] 
     }, 
     "day": { 
      "type": "pattern_capture", 
      "preserve_original": false, 
      "patterns": [ 
      "\\d{4}-\\d{2}-(\\d{2})[tT]\\d{2}:\\d{2}:\\d{2}[zZ]" 
      ] 
     }, 
     "hour": { 
      "type": "pattern_capture", 
      "preserve_original": false, 
      "patterns": [ 
      "\\d{4}-\\d{2}-\\d{2}[tT](\\d{2}):\\d{2}:\\d{2}[zZ]" 
      ] 
     }, 
     "minute": { 
      "type": "pattern_capture", 
      "preserve_original": false, 
      "patterns": [ 
      "\\d{4}-\\d{2}-\\d{2}[tT]\\d{2}:(\\d{2}):\\d{2}[zZ]" 
      ] 
     }, 
     "second": { 
      "type": "pattern_capture", 
      "preserve_original": false, 
      "patterns": [ 
      "\\d{4}-\\d{2}-\\d{2}[tT]\\d{2}:\\d{2}:(\\d{2})[zZ]" 
      ] 
     } 
     } 
    } 
    }, 
    "mappings": { 
    "test": { 
     "properties": { 
     "date": { 
      "type": "date", 
      "format": "yyyy-MM-dd'T'HH:mm:ssZ", 
      "fields": { 
      "year": { 
       "type": "string", 
       "analyzer": "year_analyzer" 
      }, 
      "month": { 
       "type": "string", 
       "analyzer": "month_analyzer" 
      }, 
      "day": { 
       "type": "string", 
       "analyzer": "day_analyzer" 
      }, 
      "hour": { 
       "type": "string", 
       "analyzer": "hour_analyzer" 
      }, 
      "minute": { 
       "type": "string", 
       "analyzer": "minute_analyzer" 
      }, 
      "second": { 
       "type": "string", 
       "analyzer": "second_analyzer" 
      } 
      } 
     } 
     } 
    } 
    } 
} 

然後,當你指數的日期,如2016-01-22T10:01:23Z,你會得到每一個填入相關的部分,即日期子場

  • date2016-01-22T10:01:23Z
  • date.year2016
  • date.month01
  • date.day22
  • date.hour10
  • date.minute01
  • date.second23

你就可以自由地聚集在任何這些子領域的得到你想要的東西。

+0

主要使用此解決方案結束。我確實添加了第二個字段來實際存儲'日',因爲我想保持日期格式符合ISO,但是這絕對簡化了解決方案。 –

+0

謝謝。我很高興這對你有幫助! – Val

+0

這很好,但是如果我想'year','month'等等是關鍵字呢? –

2

我認爲你唯一的選擇似乎是scripted upsert這將允許您在索引時運行scripts

我創造了基本指標這樣

POST user_index 
{ 
    "mappings": { 
    "users": { 
     "properties": { 
     "timestamp": { 
      "type": "date", 
      "format" : "yyyy-MM-dd'T'HH:mm:ssZ" 
     }, 
     "month":{ 
      "type" : "string" 
     }, 
     "day_of_week" : { 
      "type" : "string" 
     }, 
     "name" : { 
      "type" : "string" 
     } 
     } 
    } 
    } 
} 

那麼你應該索引你的文件這樣

POST user_index/users/111/_update/ 
{ 
    "scripted_upsert": true, 
    "script": "ctx._source.month = DateTime.parse('2014-03-01T10:30:00').toString('MMMM');ctx._source.day_of_week = DateTime.parse('2014-03-01T10:30:00').dayOfWeek().getAsText()", 
    "upsert": { 
    "name": "Brad Smith", 
    "timestamp": "2014-03-01T10:30:00Z" 
    } 
} 

這將索引文件是這樣,更多datetime操作

{ 
    "_index": "user_index", 
    "_type": "users", 
    "_id": "111", 
    "_score": 1, 
    "_source": { 
     "timestamp": "2014-03-01T10:30:00Z", 
     "day_of_week": "Saturday", 
     "name": "Brad Smith", 
     "month": "March" 
    } 
} 

現在您可以輕鬆執行aggregations。另外請注意,您必須爲此啓用dynamic scripting,最好將腳本放在config/scripts文件夾中,並將timestamp作爲params。您也可能只想根據您的要求將所有內容放入腳本中。

希望這有助於!

+0

我最終在這個實例中使用了來自@Val的解決方案,但+1提醒我關於upsert。 –

+0

很高興能幫到你! – ChintanShah25