IP 前缀聚合

编辑

一种桶聚合,它根据 IP 地址的网络或子网络对文档进行分组。一个 IP 地址由两组位组成:最高有效位表示网络前缀,最低有效位表示主机。

示例

编辑

例如,考虑以下索引

resp = client.indices.create(
    index="network-traffic",
    mappings={
        "properties": {
            "ipv4": {
                "type": "ip"
            },
            "ipv6": {
                "type": "ip"
            }
        }
    },
)
print(resp)

resp1 = client.bulk(
    index="network-traffic",
    refresh=True,
    operations=[
        {
            "index": {
                "_id": 0
            }
        },
        {
            "ipv4": "192.168.1.10",
            "ipv6": "2001:db8:a4f8:112a:6001:0:12:7f10"
        },
        {
            "index": {
                "_id": 1
            }
        },
        {
            "ipv4": "192.168.1.12",
            "ipv6": "2001:db8:a4f8:112a:6001:0:12:7f12"
        },
        {
            "index": {
                "_id": 2
            }
        },
        {
            "ipv4": "192.168.1.33",
            "ipv6": "2001:db8:a4f8:112a:6001:0:12:7f33"
        },
        {
            "index": {
                "_id": 3
            }
        },
        {
            "ipv4": "192.168.1.10",
            "ipv6": "2001:db8:a4f8:112a:6001:0:12:7f10"
        },
        {
            "index": {
                "_id": 4
            }
        },
        {
            "ipv4": "192.168.2.41",
            "ipv6": "2001:db8:a4f8:112c:6001:0:12:7f41"
        },
        {
            "index": {
                "_id": 5
            }
        },
        {
            "ipv4": "192.168.2.10",
            "ipv6": "2001:db8:a4f8:112c:6001:0:12:7f10"
        },
        {
            "index": {
                "_id": 6
            }
        },
        {
            "ipv4": "192.168.2.23",
            "ipv6": "2001:db8:a4f8:112c:6001:0:12:7f23"
        },
        {
            "index": {
                "_id": 7
            }
        },
        {
            "ipv4": "192.168.3.201",
            "ipv6": "2001:db8:a4f8:114f:6001:0:12:7201"
        },
        {
            "index": {
                "_id": 8
            }
        },
        {
            "ipv4": "192.168.3.107",
            "ipv6": "2001:db8:a4f8:114f:6001:0:12:7307"
        }
    ],
)
print(resp1)
response = client.indices.create(
  index: 'network-traffic',
  body: {
    mappings: {
      properties: {
        "ipv4": {
          type: 'ip'
        },
        "ipv6": {
          type: 'ip'
        }
      }
    }
  }
)
puts response

response = client.bulk(
  index: 'network-traffic',
  refresh: true,
  body: [
    {
      index: {
        _id: 0
      }
    },
    {
      "ipv4": '192.168.1.10',
      "ipv6": '2001:db8:a4f8:112a:6001:0:12:7f10'
    },
    {
      index: {
        _id: 1
      }
    },
    {
      "ipv4": '192.168.1.12',
      "ipv6": '2001:db8:a4f8:112a:6001:0:12:7f12'
    },
    {
      index: {
        _id: 2
      }
    },
    {
      "ipv4": '192.168.1.33',
      "ipv6": '2001:db8:a4f8:112a:6001:0:12:7f33'
    },
    {
      index: {
        _id: 3
      }
    },
    {
      "ipv4": '192.168.1.10',
      "ipv6": '2001:db8:a4f8:112a:6001:0:12:7f10'
    },
    {
      index: {
        _id: 4
      }
    },
    {
      "ipv4": '192.168.2.41',
      "ipv6": '2001:db8:a4f8:112c:6001:0:12:7f41'
    },
    {
      index: {
        _id: 5
      }
    },
    {
      "ipv4": '192.168.2.10',
      "ipv6": '2001:db8:a4f8:112c:6001:0:12:7f10'
    },
    {
      index: {
        _id: 6
      }
    },
    {
      "ipv4": '192.168.2.23',
      "ipv6": '2001:db8:a4f8:112c:6001:0:12:7f23'
    },
    {
      index: {
        _id: 7
      }
    },
    {
      "ipv4": '192.168.3.201',
      "ipv6": '2001:db8:a4f8:114f:6001:0:12:7201'
    },
    {
      index: {
        _id: 8
      }
    },
    {
      "ipv4": '192.168.3.107',
      "ipv6": '2001:db8:a4f8:114f:6001:0:12:7307'
    }
  ]
)
puts response
const response = await client.indices.create({
  index: "network-traffic",
  mappings: {
    properties: {
      ipv4: {
        type: "ip",
      },
      ipv6: {
        type: "ip",
      },
    },
  },
});
console.log(response);

const response1 = await client.bulk({
  index: "network-traffic",
  refresh: "true",
  operations: [
    {
      index: {
        _id: 0,
      },
    },
    {
      ipv4: "192.168.1.10",
      ipv6: "2001:db8:a4f8:112a:6001:0:12:7f10",
    },
    {
      index: {
        _id: 1,
      },
    },
    {
      ipv4: "192.168.1.12",
      ipv6: "2001:db8:a4f8:112a:6001:0:12:7f12",
    },
    {
      index: {
        _id: 2,
      },
    },
    {
      ipv4: "192.168.1.33",
      ipv6: "2001:db8:a4f8:112a:6001:0:12:7f33",
    },
    {
      index: {
        _id: 3,
      },
    },
    {
      ipv4: "192.168.1.10",
      ipv6: "2001:db8:a4f8:112a:6001:0:12:7f10",
    },
    {
      index: {
        _id: 4,
      },
    },
    {
      ipv4: "192.168.2.41",
      ipv6: "2001:db8:a4f8:112c:6001:0:12:7f41",
    },
    {
      index: {
        _id: 5,
      },
    },
    {
      ipv4: "192.168.2.10",
      ipv6: "2001:db8:a4f8:112c:6001:0:12:7f10",
    },
    {
      index: {
        _id: 6,
      },
    },
    {
      ipv4: "192.168.2.23",
      ipv6: "2001:db8:a4f8:112c:6001:0:12:7f23",
    },
    {
      index: {
        _id: 7,
      },
    },
    {
      ipv4: "192.168.3.201",
      ipv6: "2001:db8:a4f8:114f:6001:0:12:7201",
    },
    {
      index: {
        _id: 8,
      },
    },
    {
      ipv4: "192.168.3.107",
      ipv6: "2001:db8:a4f8:114f:6001:0:12:7307",
    },
  ],
});
console.log(response1);
PUT network-traffic
{
    "mappings": {
        "properties": {
            "ipv4": { "type": "ip" },
            "ipv6": { "type": "ip" }
        }
    }
}

POST /network-traffic/_bulk?refresh
{"index":{"_id":0}}
{"ipv4":"192.168.1.10","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f10"}
{"index":{"_id":1}}
{"ipv4":"192.168.1.12","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f12"}
{"index":{"_id":2}}
{ "ipv4":"192.168.1.33","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f33"}
{"index":{"_id":3}}
{"ipv4":"192.168.1.10","ipv6":"2001:db8:a4f8:112a:6001:0:12:7f10"}
{"index":{"_id":4}}
{"ipv4":"192.168.2.41","ipv6":"2001:db8:a4f8:112c:6001:0:12:7f41"}
{"index":{"_id":5}}
{"ipv4":"192.168.2.10","ipv6":"2001:db8:a4f8:112c:6001:0:12:7f10"}
{"index":{"_id":6}}
{"ipv4":"192.168.2.23","ipv6":"2001:db8:a4f8:112c:6001:0:12:7f23"}
{"index":{"_id":7}}
{"ipv4":"192.168.3.201","ipv6":"2001:db8:a4f8:114f:6001:0:12:7201"}
{"index":{"_id":8}}
{"ipv4":"192.168.3.107","ipv6":"2001:db8:a4f8:114f:6001:0:12:7307"}

以下聚合将文档分组到桶中。每个桶标识一个不同的子网络。通过对 ipv4 字段中的每个 IP 地址应用前缀长度为 24 的网络掩码来计算子网络

resp = client.search(
    index="network-traffic",
    size=0,
    aggs={
        "ipv4-subnets": {
            "ip_prefix": {
                "field": "ipv4",
                "prefix_length": 24
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'network-traffic',
  body: {
    size: 0,
    aggregations: {
      "ipv4-subnets": {
        ip_prefix: {
          field: 'ipv4',
          prefix_length: 24
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "network-traffic",
  size: 0,
  aggs: {
    "ipv4-subnets": {
      ip_prefix: {
        field: "ipv4",
        prefix_length: 24,
      },
    },
  },
});
console.log(response);
GET /network-traffic/_search
{
  "size": 0,
  "aggs": {
    "ipv4-subnets": {
      "ip_prefix": {
        "field": "ipv4",
        "prefix_length": 24
      }
    }
  }
}

响应

{
  ...

  "aggregations": {
    "ipv4-subnets": {
      "buckets": [
        {
          "key": "192.168.1.0",
          "is_ipv6": false,
          "doc_count": 4,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        {
          "key": "192.168.2.0",
          "is_ipv6": false,
          "doc_count": 3,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        {
           "key": "192.168.3.0",
           "is_ipv6": false,
           "doc_count": 2,
           "prefix_length": 24,
           "netmask": "255.255.255.0"
        }
      ]
    }
  }
}

要聚合 IPv6 地址,请将 is_ipv6 设置为 true

resp = client.search(
    index="network-traffic",
    size=0,
    aggs={
        "ipv6-subnets": {
            "ip_prefix": {
                "field": "ipv6",
                "prefix_length": 64,
                "is_ipv6": True
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'network-traffic',
  body: {
    size: 0,
    aggregations: {
      "ipv6-subnets": {
        ip_prefix: {
          field: 'ipv6',
          prefix_length: 64,
          "is_ipv6": true
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "network-traffic",
  size: 0,
  aggs: {
    "ipv6-subnets": {
      ip_prefix: {
        field: "ipv6",
        prefix_length: 64,
        is_ipv6: true,
      },
    },
  },
});
console.log(response);
GET /network-traffic/_search
{
  "size": 0,
  "aggs": {
    "ipv6-subnets": {
      "ip_prefix": {
        "field": "ipv6",
        "prefix_length": 64,
        "is_ipv6": true
      }
    }
  }
}

如果 is_ipv6true,则响应不包含每个桶的 netmask

{
  ...

  "aggregations": {
    "ipv6-subnets": {
      "buckets": [
        {
          "key": "2001:db8:a4f8:112a::",
          "is_ipv6": true,
          "doc_count": 4,
          "prefix_length": 64
        },
        {
          "key": "2001:db8:a4f8:112c::",
          "is_ipv6": true,
          "doc_count": 3,
          "prefix_length": 64
        },
        {
          "key": "2001:db8:a4f8:114f::",
          "is_ipv6": true,
          "doc_count": 2,
          "prefix_length": 64
        }
      ]
    }
  }
}

参数

编辑
field
(必需,字符串)要聚合的文档 IP 地址字段。字段映射类型必须为 ip
prefix_length
(必需,整数)网络前缀的长度。对于 IPv4 地址,接受的范围是 [0, 32]。对于 IPv6 地址,接受的范围是 [0, 128]
is_ipv6
(可选,布尔值)定义前缀是否应用于 IPv6 地址。仅指定 prefix_length 参数不足以知道 IP 前缀是否应用于 IPv4 或 IPv6 地址。默认为 false
append_prefix_length
(可选,布尔值)定义前缀长度是否附加到响应中的 IP 地址键。默认为 false
keyed
(可选,布尔值)定义桶在响应中是作为哈希还是作为数组返回。默认为 false
min_doc_count
(可选,整数)定义要包含在响应中的桶的最小文档数。默认为 1

响应主体

编辑
key
(字符串)IPv6 或 IPv4 子网。
prefix_length
(整数)用于聚合桶的前缀长度。
doc_count
(整数)与特定 IP 前缀匹配的文档数。
is_ipv6
(布尔值)定义网络掩码是否为 IPv6 网络掩码。
netmask
(字符串)IPv4 网络掩码。如果请求中的 is_ipv6true,则响应中缺少此字段。

键控响应

编辑

keyed 标志设置为 true,以将唯一的 IP 地址键与每个桶关联,并将子网络作为哈希而不是数组返回。

示例

resp = client.search(
    index="network-traffic",
    size=0,
    aggs={
        "ipv4-subnets": {
            "ip_prefix": {
                "field": "ipv4",
                "prefix_length": 24,
                "keyed": True
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'network-traffic',
  body: {
    size: 0,
    aggregations: {
      "ipv4-subnets": {
        ip_prefix: {
          field: 'ipv4',
          prefix_length: 24,
          keyed: true
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "network-traffic",
  size: 0,
  aggs: {
    "ipv4-subnets": {
      ip_prefix: {
        field: "ipv4",
        prefix_length: 24,
        keyed: true,
      },
    },
  },
});
console.log(response);
GET /network-traffic/_search
{
  "size": 0,
  "aggs": {
    "ipv4-subnets": {
      "ip_prefix": {
        "field": "ipv4",
        "prefix_length": 24,
        "keyed": true
      }
    }
  }
}

响应

{
  ...

  "aggregations": {
    "ipv4-subnets": {
      "buckets": {
        "192.168.1.0": {
          "is_ipv6": false,
          "doc_count": 4,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        "192.168.2.0": {
          "is_ipv6": false,
          "doc_count": 3,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        "192.168.3.0": {
          "is_ipv6": false,
          "doc_count": 2,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        }
      }
    }
  }
}

将前缀长度附加到 IP 地址键

编辑

append_prefix_length 标志设置为 true,以将 IP 地址键与子网络的网络前缀长度连接起来。

示例

resp = client.search(
    index="network-traffic",
    size=0,
    aggs={
        "ipv4-subnets": {
            "ip_prefix": {
                "field": "ipv4",
                "prefix_length": 24,
                "append_prefix_length": True
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'network-traffic',
  body: {
    size: 0,
    aggregations: {
      "ipv4-subnets": {
        ip_prefix: {
          field: 'ipv4',
          prefix_length: 24,
          append_prefix_length: true
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "network-traffic",
  size: 0,
  aggs: {
    "ipv4-subnets": {
      ip_prefix: {
        field: "ipv4",
        prefix_length: 24,
        append_prefix_length: true,
      },
    },
  },
});
console.log(response);
GET /network-traffic/_search
{
  "size": 0,
  "aggs": {
    "ipv4-subnets": {
      "ip_prefix": {
        "field": "ipv4",
        "prefix_length": 24,
        "append_prefix_length": true
      }
    }
  }
}

响应

{
  ...

  "aggregations": {
    "ipv4-subnets": {
      "buckets": [
        {
          "key": "192.168.1.0/24",
          "is_ipv6": false,
          "doc_count": 4,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        {
          "key": "192.168.2.0/24",
          "is_ipv6": false,
          "doc_count": 3,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        {
          "key": "192.168.3.0/24",
          "is_ipv6": false,
          "doc_count": 2,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        }
      ]
    }
  }
}

最小文档计数

编辑

使用 min_doc_count 参数仅返回具有最小文档数的桶。

resp = client.search(
    index="network-traffic",
    size=0,
    aggs={
        "ipv4-subnets": {
            "ip_prefix": {
                "field": "ipv4",
                "prefix_length": 24,
                "min_doc_count": 3
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'network-traffic',
  body: {
    size: 0,
    aggregations: {
      "ipv4-subnets": {
        ip_prefix: {
          field: 'ipv4',
          prefix_length: 24,
          min_doc_count: 3
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "network-traffic",
  size: 0,
  aggs: {
    "ipv4-subnets": {
      ip_prefix: {
        field: "ipv4",
        prefix_length: 24,
        min_doc_count: 3,
      },
    },
  },
});
console.log(response);
GET /network-traffic/_search
{
  "size": 0,
  "aggs": {
    "ipv4-subnets": {
      "ip_prefix": {
        "field": "ipv4",
        "prefix_length": 24,
        "min_doc_count": 3
      }
    }
  }
}

响应

{
  ...

  "aggregations": {
    "ipv4-subnets": {
      "buckets": [
        {
          "key": "192.168.1.0",
          "is_ipv6": false,
          "doc_count": 4,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        },
        {
          "key": "192.168.2.0",
          "is_ipv6": false,
          "doc_count": 3,
          "prefix_length": 24,
          "netmask": "255.255.255.0"
        }
      ]
    }
  }
}