Regexp не работает в ES DSL-запрос

Отображение моего поиска Elastic выглядит следующим образом:

{
  "settings": {
    "index": {
      "number_of_shards": "5",
      "number_of_replicas": "1"
    }
  },
  "mappings": {
    "node": {
      "properties": {
        "field1": {
          "type": "keyword"
        },
        "field2": {
          "type": "keyword"
        },
        "query": {
          "properties": {
            "regexp": {
              "properties": {
                "field1": {
                  "type": "keyword"
                },
                "field2": {
                  "type": "keyword"
                }
              }
            }
          }
        }
      }
    }
  }
}

Проблема в следующем:

Я формирую ES-запросы с использованием asticsearch_dsl Q(). Он прекрасно работает в большинстве случаев, когда мой запрос содержит какие-либо сложные регулярные выражения. Но он полностью потерпит неудачу, если он содержит символ регулярного выражения '!' в этом. Это не дает никакого результата, когда поисковый термин содержит "!" в этом.

Например:

1.) Q('regexp', field1 = "^[a-z]{3}.b.*") (работает отлично)

2.) Q('regexp', field1 = "^f04.*") (работает отлично)

3.)Q('regexp', field1 = "f00.*") (работает отлично)

4.) Q('regexp', field1 = "f04baz?") (работает отлично)

Сбой в нижнем случае:

5.) Q('regexp', field1 = "f04((?!z).)*") (Не дает результатов вообще)

Я попытался добавить "анализатор": "ключевое слово" вместе с "тип": "ключевое слово", как указано выше, в полях, но в этом случае ничего не работает.

В браузере я попытался проверить, как анализатор: ключевое слово будет работать на входе в случае, если это не удается:

http://localhost:9210/search/_analyze?analyzer=keyword&text=f04((?!z).)*

Кажется, выглядит хорошо здесь с результатом:

{
  "tokens": [
    {
      "token": "f04((?!z).)*",
      "start_offset": 0,
      "end_offset": 12,
      "type": "word",
      "position": 0
    }
  ]
}

Я выполняю свои запросы, как показано ниже:

search_obj = Search(using = _conn, index = _index, doc_type = _type).query(Q('regexp', field1 = "f04baz?"))
count = search_obj.count()
response = search_obj[0:count].execute()
logger.debug("total nodes(hits):" + " " + str(response.hits.total))

Пожалуйста, помогите, это действительно досадная проблема, так как все символы регулярного выражения прекрасно работают во всех запросах, кроме!

Кроме того, как я могу проверить, какой анализатор в настоящее время применяется с вышеуказанными настройками в моих сопоставлениях?

1 ответ

Решение

Механизм регулярных выражений Lucene ElasticSearch не поддерживает любые типы обходных путей. Документация по регулярным выражениям ES довольно двусмысленна, говоря о том, что .* очень медленный, а также использование регулярных выражений с поиском (что не только неоднозначно, но и неправильно), так как обходные пути, если их использовать с умом, могут значительно ускорить сопоставление регулярных выражений).

Поскольку вы хотите сопоставить любую строку, которая содержит f04 и не содержит z вы можете использовать

[^z]*fo4[^z]*

подробности

  • [^z]* - любые 0+ символов кроме z
  • fo4 - fo4 подстрока
  • [^z]* - любые 0+ символов кроме z,

Если у вас есть строка из нескольких символов, которую нужно "исключить" (скажем, z4 скорее, чем z), вы можете использовать свой подход, используя оператор дополнения:

.*f04.*&~(.*z4.*)

Это означает почти то же самое, но не поддерживает разрывы строк:

  • .* - любые символы кроме новой строки, как можно больше
  • f04 - f04
  • .* - любые символы кроме новой строки, как можно больше
  • & - А ТАКЖЕ
  • ~(.*z4.*) - любая строка, кроме той, которая имеет z4
Другие вопросы по тегам