У нас есть индекс с полем ключевого слова, которое очень часто является IP-адресом, но не всегда. Мы хотели бы иметь возможность выполнять поиск по этому индексу в этом поле, используя не только ключевые слова, но и нотацию CIDR, которая поддерживается только для полей типа «ip». На первый взгляд, это выглядит как вариант использования нескольких полей, поэтому у нас есть индекс с сопоставлениями:

{
    "mappings": {
        "my_field": {
            "type": "keyword"
            "fields": {
                "ip": {
                    "type": "ip"
                    "ignore_malformed": true
                }  
            }
        }
    }
}

Итак, когда у нашего приложения есть набор не-IP-адресов, IP-адресов и блоков / диапазонов IP-адресов в нотации CIDR и требуется запрос по ним, наше приложение разбивает этот набор на один набор с не-IP-адресами, а другой с IP-адреса / CIDR-нотация блокирует и делает из них два отдельных фильтра терминов в моем запросе, например:

{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "my_field.ip": [
              "123.123.123.0/24",
              "192.168.0.1",
              "192.168.16.255",
              "192.169.1.0/24"
            ]
          }
        },
        {
          "terms": {
            "my_field": [
              "someDomain.com",
              "notAnIp.net"
            ]
          }
        }
      ]
    }
  }
}

Это не возвращает записей. Я предполагаю, потому что он не рассматривает два фильтра как ИЛИ. Мне нужны все записи, соответствующие первому запросу терминов, ПЛЮС все записи, соответствующие второму запросу терминов. Как лучше всего этого добиться? Надеюсь, моему приложению не нужно отправлять два отдельных запроса.

1
b15 1 Дек 2020 в 18:59

2 ответа

Лучший ответ

Попробуйте этот запрос ниже:

{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "filter": {
              "terms": {
                "my_field.ip": [
                  "123.123.123.0/24",
                  "192.168.0.1",
                  "192.168.16.255",
                  "192.169.1.0/24"
                ]
              }
            }
          }
        },
        {
          "bool": {
            "filter": {
              "terms": {
                "my_field": [
                  "someDomain.com",
                  "notAnIp.net"
                ]
              }
            }
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}
1
ESCoder 1 Дек 2020 в 16:04

Вы неправильно поняли предложение фильтра, он будет фильтровать документы без предложения should или must в вашем логическом запросе, см. логическое значение запрашивает официальный документ для получения дополнительной информации.

Когда вы используете предложение should или must с фильтром, его значение изменяется, и он начинает возвращать документы, обратитесь к ответу @ESCoder о том, как этого добиться.

Также обратите внимание, поскольку вы используете только предложение фильтра, оценка не будет рассчитываться, и все документы в ваших результатах поиска будут иметь такую же оценку, как 0, что может быть не тем, что вам нужно, если вы хотите оценка, то вам нужно использовать предложение запроса.

1
Elasticsearch Ninja 1 Дек 2020 в 16:14