elasticsearch聚合,排序,脚本处理文本数据查询异常
今天执行一个聚合查询操作时发生异常,相关信息如下:
执行聚合查询命令如下:
GET /megacorp/_search
{
"aggs" : {
"all_interests" : {
"terms" : { "field" : "interests" }
}
}
}
异常信息:
{
"type" : "illegal_argument_exception",
"reason" : "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [field_data] in order to load field data by uninverting the inverted index. Note that this can use significant memory."
}
具体原因是由于Text类型字段被分析时,通过分析器将该字符串转换成单独字符集合(a list of individual terms)后进行索引.这样elasticsearch就可以实现在全文检索中查询指定单词.Text字段默认是可查询的,但是Text字段不用于排序,聚合和脚本处理中.
那么如何实现聚合和排序那?
其实上面的异常提示中已经介绍了如何进行聚合排序,具体方式如下:
- 1 (推荐方式)在Text类型字段上增加keyword参数.这是字段就具备了全文检索能力(text)和聚合排序能力(keyword).
- 2 使用fielddata内存处理能力.如果要对分析后文本字段进行聚合排序或执行脚本处理文本时,只能使用fielddata方式.
keyword使用方式:
a. 增加keyword字段参数,即fields.keyword的定义
添加索引字段映射,即将about字段映射为text类型和keyword类型
PUT /indexname
{
"mappings": {
"properties": {
"about":{
"type": "text",
"fields":{
"keyword":{
"type":"keyword"
}
}
}
}
}
}
b. 增加文档数据
PUT indexname/_doc/1
{
"about":"aaa"
}
PUT indexname/_doc/2
{
"about":"bbb"
}
c.进行数据查询并通过about.keyword进行排序
GET indexname/_search
{
"sort": [
{
"about.keyword": {
"order": "desc"
}
}
]
}
fielddata使用方式:
a. 添加索引映射
PUT indexname/_mapping
{
"properties": {
"about": {
"type": "text",
"fielddata": true
}
}
}
b.查询
GET indexname/_search
{
"sort": [
{
"about": {
"order": "desc"
}
}
]
}
一般不推荐在Text字段上启用fielddata,因为field data和其缓存存储在堆中,这使得它们的计算成本很高.计算这些字段会造成延迟,增加的堆占用会造成集群性能问题.
这keyword和fielddata两种方式的区别除了具体实现方式外,主要在于是否要求对于文本字段进行解析操作,由于keyword不要求进行文本解析,所以它的效率更高.