Elasticsearch 根据字段值去重前的个数过滤数据(qbit)

前言

  • 本文对 Elasticsearch 7.17 适用
  • 假定有个 ip 类型的字段 client_ip,需要根据字段值的个数过滤数据
  • query 中使用 script 只能通过 doc['client_ip'] 获取到去重后的个数
  • 研究发现使用 runtime_mappings 可以动态新建字段获取到不去重的个数

示例

  • 创建索引
PUT my_index
{
  "mappings": {
    "dynamic": false,
    "properties": {
      "client_ip": {
        "type": "ip"
      }
    }
  }
}
  • 写入数据
POST my_index/_bulk
{ "index": { "_id": "1" } }
{ "client_ip": "192.168.0.1"}
{ "index": { "_id": "2" } }
{ "client_ip": ["192.168.0.2", "192.168.0.2"]}
{ "index": { "_id": "3" } }
{ "client_ip":  ["192.168.0.1", "192.168.0.2"]}
  • 想要查询 client_ip 个数为 1 的数据(根据去重后的个数查询)
GET my_index/_search
{
  "query": {
    "script": {
      "script": {
        "source": "doc['client_ip'].size() == params.size",
        "params": {
          "size": 1
        }
      }
    }
  }
}

查询到 2 条数据,第 2 条重复值数据实际上并不需要返回

192.168.0.1
["192.168.0.2", "192.168.0.2"]
  • 改为生成动态字段查询(根据去重前的个数查询)
GET my_index/_search
{
  "runtime_mappings": {
    "ip_count": {
      "type": "long",
      "script": {
        "source": """
          def ips = params._source.client_ip;
          if (ips == null) {
            emit(0);
          } else if (ips instanceof List) {
            emit(ips.size());
          } else {
            emit(1);
          }
        """
      }
    }
  },
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "ip_count": {
              "value": 1
            }
          }
        }
      ]
    }
  }
}

查询到 1 条数据,符合需求

192.168.0.1 
本文出自 qbit snap

你可能感兴趣的:(Elasticsearch 根据字段值去重前的个数过滤数据(qbit))