在使用 Elasticsearch 搜索 IP 地址时,我们可以把数据类型定义为 IP 数据类型。这样我们可以针对 IP 地址进行搜索。这种 IP 地址可以是 IPv4 或者是 IPv6 的形式。
现在假设我们导入一个如下的数据到 Elasticsearch 中:
PUT my-index/_doc/1
{
"ip_addr": "192.168.1.1"
}
在没有定义数据类型的情况下, Elasticsearch 会把上面的字段 ip_add 映射到一个 text 及 keyword 的类型的数据上:
GET my-index/_mapping
上面命令显示的结果为:
{
"my-index" : {
"mappings" : {
"properties" : {
"ip_addr" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
假如我们想对上面的数据进行如下的搜索:
GET my-index/_search
{
"query": {
"term": {
"ip_addr": "192.168.0.0/16"
}
}
}
针对上面的搜索,我稍微做一下解释:对于上面的 IPv4 的 IP 地址含有4个 bytes,而每个 byte 含有8个 digits。在上面的 /16 即表示前面的 16 位的 digits,也即 192.168。我们可以这么说任何一个 IP 地址位于 192.168.0.0 至 192.168.255.255 都在这个范围内。
上面的搜索的结果是:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
也就是找不到任何的结果。这是什么原因呢?
就其原因,是因为我们没有正确地把 IP 的数据类型定义为 IP 数据类型。我们重新来定义这个索引的 mapping:
DELETE my-index
PUT my-index
{
"mappings": {
"properties": {
"ip_addr": {
"type": "ip"
}
}
}
}
PUT my-index/_doc/1
{
"ip_addr": "192.168.1.1"
}
我们按照上面的步骤来重新建立索引,并导入文档。我们在按照如下的方法来进行搜索:
GET my-index/_search
{
"query": {
"term": {
"ip_addr": "192.168.0.0/16"
}
}
}
上面的命令显示的结果为:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"ip_addr" : "192.168.1.1"
}
}
]
}
}
这次,显然我们搜索到我们需要的文档了,这是因为 192.168.1.1 是属于 IP 地址范围 192.168.0.0/16 的。我们可以通过这样的方法搜索属于一个 IP 范围的日志文件供我们查询。