由唯一子字符串聚合的Elasticsearch查询(电子邮件域)

idc*_*ark 5 aggregation elasticsearch

我有一个弹性搜索查询,它查询索引,然后根据特定字段进行聚合sender_not_analyzed.然后,我在同一个字段上使用术语聚合sender_not_analyzed,返回顶部"发件人"的存储桶.我的查询目前是:

{
   "size": 0,
   "query": {
      "regexp": {
         "sender_not_analyzed": ".*[@].*"
      }
   },
   "aggs": {
      "sender-stats": {
         "terms": {
            "field": "sender_not_analyzed"
         }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

返回看起来像这样的桶:

"aggregations": {
      "sender-stats": {
         "buckets": [
            {
               "key": "<Mike <mike@fizzbuzz.com>@MISSING_DOMAIN>",
               "doc_count": 5017
            },
            {
               "key": "jon.doe@foo.com",
               "doc_count": 3963
            },
            {
               "key": "jane.doe@foo.com",
               "doc_count": 2857
            },
            {
              "key": "jon.doe@bar.com",
              "doc_count":1544
            }
Run Code Online (Sandbox Code Playgroud)

我如何编写聚合,以便为每个唯一的电子邮件域获取单个存储桶,例如,foo.com将具有doc_count(3963 + 2857)6820?我可以使用正则表达式聚合来完成此操作,还是需要编写某种自定义分析器来将@中的字符串拆分为字符串的末尾?

Chi*_*h25 3

这已经很晚了,但我认为这可以通过使用pattern_replace char过滤器来完成,您可以使用捕获域名regex,这是我的设置

POST email_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "char_filter": [
            "domain"
          ],
          "tokenizer": "keyword",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      },
      "char_filter": {
        "domain": {
          "type": "pattern_replace",
          "pattern": ".*@(.*)",
          "replacement": "$1"
        }
      }
    }
  },
  "mappings": {
    "your_type": {
      "properties": {
        "domain": {
          "type": "string",
          "analyzer": "my_custom_analyzer"
        },
        "sender_not_analyzed": {
          "type": "string",
          "index": "not_analyzed",
          "copy_to": "domain"
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这里domain char filter将捕获域名,我们需要使用关键字分词器来获取域名,我使用的是lowercase过滤器,但是否使用它取决于你。使用copy_to参数复制sender_not_analyzedtodomain字段的值,虽然_source字段不会被修改以包含该值,但我们可以查询它。

GET email_index/_search
{
  "size": 0,
  "query": {
    "regexp": {
      "sender_not_analyzed": ".*[@].*"
    }
  },
  "aggs": {
    "sender-stats": {
      "terms": {
        "field": "domain"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这会给你想要的结果。