IP range aggregation

edit

Just like the dedicated date range aggregation, there is also a dedicated range aggregation for IP typed fields:

Example:

response = client.search(
  index: 'ip_addresses',
  body: {
    size: 10,
    aggregations: {
      ip_ranges: {
        ip_range: {
          field: 'ip',
          ranges: [
            {
              to: '10.0.0.5'
            },
            {
              from: '10.0.0.5'
            }
          ]
        }
      }
    }
  }
)
puts response
GET /ip_addresses/_search
{
  "size": 10,
  "aggs": {
    "ip_ranges": {
      "ip_range": {
        "field": "ip",
        "ranges": [
          { "to": "10.0.0.5" },
          { "from": "10.0.0.5" }
        ]
      }
    }
  }
}

Response:

{
  ...

  "aggregations": {
    "ip_ranges": {
      "buckets": [
        {
          "key": "*-10.0.0.5",
          "to": "10.0.0.5",
          "doc_count": 10
        },
        {
          "key": "10.0.0.5-*",
          "from": "10.0.0.5",
          "doc_count": 260
        }
      ]
    }
  }
}

IP ranges can also be defined as CIDR masks:

response = client.search(
  index: 'ip_addresses',
  body: {
    size: 0,
    aggregations: {
      ip_ranges: {
        ip_range: {
          field: 'ip',
          ranges: [
            {
              mask: '10.0.0.0/25'
            },
            {
              mask: '10.0.0.127/25'
            }
          ]
        }
      }
    }
  }
)
puts response
GET /ip_addresses/_search
{
  "size": 0,
  "aggs": {
    "ip_ranges": {
      "ip_range": {
        "field": "ip",
        "ranges": [
          { "mask": "10.0.0.0/25" },
          { "mask": "10.0.0.127/25" }
        ]
      }
    }
  }
}

Response:

{
  ...

  "aggregations": {
    "ip_ranges": {
      "buckets": [
        {
          "key": "10.0.0.0/25",
          "from": "10.0.0.0",
          "to": "10.0.0.128",
          "doc_count": 128
        },
        {
          "key": "10.0.0.127/25",
          "from": "10.0.0.0",
          "to": "10.0.0.128",
          "doc_count": 128
        }
      ]
    }
  }
}

Keyed Response

edit

Setting the keyed flag to true will associate a unique string key with each bucket and return the ranges as a hash rather than an array:

response = client.search(
  index: 'ip_addresses',
  body: {
    size: 0,
    aggregations: {
      ip_ranges: {
        ip_range: {
          field: 'ip',
          ranges: [
            {
              to: '10.0.0.5'
            },
            {
              from: '10.0.0.5'
            }
          ],
          keyed: true
        }
      }
    }
  }
)
puts response
GET /ip_addresses/_search
{
  "size": 0,
  "aggs": {
    "ip_ranges": {
      "ip_range": {
        "field": "ip",
        "ranges": [
          { "to": "10.0.0.5" },
          { "from": "10.0.0.5" }
        ],
        "keyed": true
      }
    }
  }
}

Response:

{
  ...

  "aggregations": {
    "ip_ranges": {
      "buckets": {
        "*-10.0.0.5": {
          "to": "10.0.0.5",
          "doc_count": 10
        },
        "10.0.0.5-*": {
          "from": "10.0.0.5",
          "doc_count": 260
        }
      }
    }
  }
}

It is also possible to customize the key for each range:

response = client.search(
  index: 'ip_addresses',
  body: {
    size: 0,
    aggregations: {
      ip_ranges: {
        ip_range: {
          field: 'ip',
          ranges: [
            {
              key: 'infinity',
              to: '10.0.0.5'
            },
            {
              key: 'and-beyond',
              from: '10.0.0.5'
            }
          ],
          keyed: true
        }
      }
    }
  }
)
puts response
GET /ip_addresses/_search
{
  "size": 0,
  "aggs": {
    "ip_ranges": {
      "ip_range": {
        "field": "ip",
        "ranges": [
          { "key": "infinity", "to": "10.0.0.5" },
          { "key": "and-beyond", "from": "10.0.0.5" }
        ],
        "keyed": true
      }
    }
  }
}

Response:

{
  ...

  "aggregations": {
    "ip_ranges": {
      "buckets": {
        "infinity": {
          "to": "10.0.0.5",
          "doc_count": 10
        },
        "and-beyond": {
          "from": "10.0.0.5",
          "doc_count": 260
        }
      }
    }
  }
}