我想运行一个查询来过滤掉像
123.[16-31].0.*
这样的 IP 范围(包括 16 和 31)。通用示例:
GET _search
{
"query": {
"bool": {
"must": {
"match_phrase": {
"somefield": "somevalue"
}
},
"must_not": {
... ip filter ...
}
}
}
}
must_not
部分怎么写?
似乎有效的解决方案是将 16 个范围放入
must_not
:
"must_not": [
{
"range": {
"host.ip": {
"gte": "123.16.0.0",
"lte": "123.16.0.255"
}
}
},
.... same for 17 until 30
{
"range": {
"host.ip": {
"gte": "123.31.0.0",
"lte": "123.31.0.255"
}
}
}
]
但是需要花很多时间才能写下来。我很想使用正则表达式,例如:
"must_not": {
"regexp": {
"host.ip": "123.(1[6-9]|2[0-9]|30|31).0.*"
}
}
但显然它失败了
Can only use regexp queries on keyword and text fields - not on [host.ip] which is of type [ip]
。
生成 16 个范围是最快的解决方案。但是,如果您不运行此请求太多次,并且更愿意用一些 CPU 时间换取程序员的时间,则可以使用运行时映射将
ip
字段转换为 keyword
字段。这样,您就可以像对待任何其他文本字段一样对待该字段。所以,你可以这样做:
DELETE test
PUT test
{
"mappings": {
"properties": {
"host": {
"properties": {
"ip": {
"type": "ip"
}
}
}
}
}
}
POST test/_bulk?refresh
{"index":{}}
{"host":{"ip":"123.16.0.1"}}
{"index":{}}
{"host":{"ip":"123.16.1.0"}}
{"index":{}}
{"host":{"ip":"124.16.0.1"}}
POST test/_search
{
"runtime_mappings": {
"host.ip_string": {
"type": "keyword",
"script": {
"source": "emit(doc['host.ip'].value);"
}
}
},
"query": {
"bool": {
"must_not": [
{
"regexp": {
"host.ip_string": "123.(1[6-9]|2[0-9]|30|31).0.*"
}
}
]
}
}
}
或者更好的是这样的:
POST test/_search
{
"runtime_mappings": {
"host.ip_string": {
"type": "keyword",
"script": {
"source": "emit(doc['host.ip'].value);"
}
}
},
"query": {
"bool": {
"must_not": [
{
"regexp": {
"host.ip_string": "123\\.<16-31>\\.0\\..*"
}
}
]
}
}
}