Elasticsearch - 按键字符串长度对 Terms 聚合结果进行排序

Elasticsearch - Sort results of Terms aggregation by key string length

我正在使用 Terms 聚合查询 ES 以查找字符串字段 foo 的第一个 N 个唯一值,其中该字段包含一个子字符串 bar,并且文档匹配一些其他约束。

目前我可以按关键字字符串的字母顺序对结果进行排序:

{
  "query": {other constraints},
  "aggs": {
    "my_values": {
      "terms": {
        "field": "foo.raw",
        "include": ".*bar.*",
        "order": {"_key": "asc"},
        "size": N
      }
    }
  }
}

这样的结果类似于

{
  ...
  "aggregations": {
    "my_values": {
      "doc_count_error_upper_bound": 0,   
      "sum_other_doc_count": 145,           
      "buckets": [                        
        {
          "key": "aa_bar_aa",
          "doc_count": 1
        },
        {
          "key": "iii_bar_iii",
          "doc_count": 1
        },
        {
          "key": "z_bar_z",
          "doc_count": 1
       }
      ]
    }
  }
}

如何更改 order 选项,使存储桶按 foo 键字段中的字符串长度排序,从而使结果类似于

{
  ...
  "aggregations": {
    "my_values": {
      "doc_count_error_upper_bound": 0,   
      "sum_other_doc_count": 145,           
      "buckets": [                        
        {
          "key": "z_bar_z",
          "doc_count": 1
        },
        {
          "key": "aa_bar_aa",
          "doc_count": 1
        },
        {
          "key": "iii_bar_iii",
          "doc_count": 1
        }
      ]
    }
  }
}

这是需要的,因为较短的字符串更接近搜索子字符串,因此被认为是 'better' 匹配项,因此在结果中应该比较长的字符串更早出现。 根据桶与原始子字符串的相似程度对桶进行排序的任何替代方法也会有所帮助。

我需要在 ES 中进行排序,这样我只需从 ES 加载前 N 个结果。

我想出了一个方法来做到这一点。 我使用每个动态桶的子聚合来计算密钥字符串的长度作为另一个字段。 然后我能够首先按这个新的长度字段排序,然后按实际键排序,因此相同长度的键按字母顺序排序。

{
  "query": {other constraints},
  "aggs": {
    "my_values": {
      "terms": {
        "field": "foo.raw",
        "include": ".*bar.*",
        "order": [
          {"key_length": "asc"},
          {"_key": "asc"}
        ],
        "size": N
      },
      "aggs": {
        "key_length": {
          "max": {"script": "doc['foo.raw'].value.length()" }
        }
      }
    }
  }
}

这给了我这样的结果

{
  ...
  "aggregations": {
    "my_values": {
      "doc_count_error_upper_bound": 0,   
      "sum_other_doc_count": 145,           
      "buckets": [                        
        {
          "key": "z_bar_z",
          "doc_count": 1
        },
        {
          "key": "aa_bar_aa",
          "doc_count": 1
        },
        {
          "key": "dd_bar_dd",
          "doc_count": 1
        },
        {
          "key": "bbb_bar_bbb",
          "doc_count": 1
        }
      ]
    }
  }
}

这就是我想要的。